--- ./channels/ooh323cDriver.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323cDriver.h 2009-07-28 22:49:05.000000000 +0400 @@ -27,6 +27,7 @@ #define H323_DTMF_H245ALPHANUMERIC (1 << 2) #define H323_DTMF_H245SIGNAL (1 << 3) #define H323_DTMF_INBAND (1 << 4) +#define H323_DTMF_INBANDRELAX (1 << 8) struct h323_pvt; int ooh323c_start_stack_thread(void); @@ -35,5 +36,5 @@ (struct ast_codec_pref *prefs, int capability, int dtmf); int convertH323CapToAsteriskCap(int cap); 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 t38support); #endif --- ./channels/chan_ooh323.h 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/chan_ooh323.h 2009-07-28 22:49:05.000000000 +0400 @@ -61,6 +61,8 @@ #include #include +#include + #include "ootypes.h" #include "ooCapability.h" #include "oochannels.h" --- ./channels/Makefile 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/Makefile 2009-07-29 00:46:18.000000000 +0400 @@ -26,6 +26,7 @@ h323/MULTIMEDIA-SYSTEM-CONTROLDec.o h323/MULTIMEDIA-SYSTEM-CONTROLEnc.o H323CFLAGS=-Iooh323c/src -Iooh323c/src/h323 +ASTCFLAGS+=-g all: _all @@ -38,5 +39,7 @@ chan_ooh323.o: ASTCFLAGS+=$(H323CFLAGS) +chan_ooh323.so: ASTLDFLAGS+=-lrt -lspandsp + $(if $(filter chan_ooh323,$(EMBEDDED_MODS)),modules.link,chan_ooh323.so): ASTCFLAGS+=$(H323CFLAGS) $(if $(filter chan_ooh323,$(EMBEDDED_MODS)),modules.link,chan_ooh323.so): $(addprefix ooh323c/src/,$(H323OBJS)) chan_ooh323.o ooh323cDriver.o --- ./channels/chan_ooh323.c 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/chan_ooh323.c 2009-07-29 02:51:38.000000000 +0400 @@ -16,6 +16,14 @@ #include "chan_ooh323.h" +#include + +#define HAVE_SPANDSP_EXPOSE_H +#include +#ifdef HAVE_SPANDSP_EXPOSE_H +#include +#endif +#include /* Defaults */ #define DEFAULT_CONTEXT "default" @@ -32,6 +40,13 @@ #define H323_ALREADYGONE (1<<5) #define H323_NEEDDESTROY (1<<6) #define H323_DISABLEGK (1<<7) +#define H323_NEEDSTART (1<<8) + +#define MAXT30 240 +#define T38TOAUDIOTIMEOUT 30 +#define T38_DISABLED 0 +#define T38_TRANSPARENT 1 +#define T38_FAXGW 2 /* Channel description */ static const char type[] = "OOH323"; @@ -50,6 +65,7 @@ static struct ast_frame *ooh323_read(struct ast_channel *ast); static int ooh323_write(struct ast_channel *ast, struct ast_frame *f); static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen); +static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen); static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp); @@ -57,11 +73,12 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active); -static void print_codec_to_cli(int fd, struct ast_codec_pref *pref); +static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan); +static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl); -#if 0 +static void print_codec_to_cli(int fd, struct ast_codec_pref *pref); static void ast_ooh323c_exit(); -#endif + static const struct ast_channel_tech ooh323_tech = { .type = type, @@ -79,7 +96,8 @@ .indicate = ooh323_indicate, .fixup = ooh323_fixup, .send_html = 0, - .bridge = ast_rtp_bridge, + .queryoption = ooh323_queryoption, + /* .bridge = ast_rtp_bridge, */ }; static struct ast_rtp_protocol ooh323_rtp = { @@ -89,12 +107,37 @@ .set_rtp_peer = ooh323_set_rtp_peer }; +static struct ast_udptl_protocol ooh323_udptl = { + type: "H323", + get_udptl_info: ooh323_get_udptl_peer, + set_udptl_peer: ooh323_set_udptl_peer, +}; + + + +struct ooh323_user; + /* H.323 channel private structure */ static struct ooh323_pvt { ast_mutex_t lock; /* Channel private lock */ struct ast_rtp *rtp; struct ast_rtp *vrtp; /* Placeholder for now */ + + int t38support; /* T.38 mode - disable, transparent, faxgw */ + struct ast_udptl *udptl; + int faxmode; + int t38_tx_enable; + int t38_init; + t38_gateway_state_t t38r_state; + struct sockaddr_in udptlredirip; + time_t lastTxT38; + int chmodepend; + struct ast_channel *owner; /* Master Channel */ + union { + char *user; /* cooperating user/peer */ + char *peer; + } neighbor; time_t lastrtptx; time_t lastrtprx; unsigned int flags; @@ -124,6 +167,7 @@ char accountcode[256]; /* Account code */ int nat; int amaflags; + int progsent; /* progress is sent */ struct ast_dsp *vad; struct ooh323_pvt *next; /* Next entity */ } *iflist = NULL; @@ -143,6 +187,7 @@ int capability; struct ast_codec_pref prefs; int dtmfmode; + int t38support; int rtptimeout; int mUseIP; /* Use IP address or H323-ID to search user */ char mIP[20]; @@ -160,6 +205,7 @@ char accountcode[20]; int amaflags; int dtmfmode; + int t38support; int mFriend; /* indicates defined as friend */ char ip[20]; int port; @@ -193,35 +239,50 @@ AST_MUTEX_DEFINE_STATIC(ooh323c_cmd_lock); +static long callnumber = 0; +AST_MUTEX_DEFINE_STATIC(ooh323c_cn_lock); + /* stack callbacks */ int onAlerting(ooCallData *call); +int onProgress(ooCallData *call); int onNewCallCreated(ooCallData *call); +int onOutgoingCall(ooCallData *call); int onCallEstablished(ooCallData *call); int onCallCleared(ooCallData *call); +void onModeChanged(ooCallData *call, int t38mode); static char gLogFile[256] = DEFAULT_LOGFILE; static int gPort = 1720; static char gIP[20]; -static char gCallerID[AST_MAX_EXTENSION] = DEFAULT_H323ID; +static char gCallerID[AST_MAX_EXTENSION] = ""; static struct ooAliases *gAliasList; static int gCapability = AST_FORMAT_ULAW; static struct ast_codec_pref gPrefs; static int gDTMFMode = H323_DTMF_RFC2833; +static int gT38Support = T38_FAXGW; static char gGatekeeper[100]; static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper; static int gIsGateway = 0; static int gFastStart = 1; static int gTunneling = 1; +static int gBeMaster = 0; static int gMediaWaitForConnect = 0; static int gTOS = 0; static int gRTPTimeout = 60; static char gAccountcode[80] = DEFAULT_H323ACCNT; static int gAMAFLAGS; static char gContext[AST_MAX_EXTENSION] = DEFAULT_CONTEXT; -static int gIncomingLimit = 4; -static int gOutgoingLimit = 4; +static int gIncomingLimit = 1024; +static int gOutgoingLimit = 1024; OOBOOL gH323Debug = FALSE; +static int gTRCLVL = OOTRCLVLERR; + +static int t35countrycode = 0; +static int t35extensions = 0; +static int manufacturer = 0; +static char vendor[AST_MAX_EXTENSION] = ""; +static char version[AST_MAX_EXTENSION] = ""; static struct ooh323_config { @@ -244,7 +305,7 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, - const char *host) + const char *host, int capability) { struct ast_channel *ch = NULL; int fmt; @@ -254,28 +315,38 @@ /* Don't hold a h323 pvt lock while we allocate a channel */ ast_mutex_unlock(&i->lock); - ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, i->accountcode, i->exten, i->context, i->amaflags, "OOH323/%s-%08x", host, i); + ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, + i->accountcode, i->exten, i->context, i->amaflags, + "OOH323/%s-%ld", host, callnumber); + ast_mutex_lock(&ooh323c_cn_lock); + callnumber++; + ast_mutex_unlock(&ooh323c_cn_lock); + ast_mutex_lock(&i->lock); if (ch) { ast_channel_lock(ch); ch->tech = &ooh323_tech; - ch->nativeformats = i->capability; - - fmt = ast_best_codec(ch->nativeformats); - - ch->fds[0] = ast_rtp_fd(i->rtp); - ch->fds[1] = ast_rtcp_fd(i->rtp); + fmt = ast_codec_pref_index(&i->prefs, 0); + if (!fmt) + fmt = ast_best_codec(capability); + + ch->nativeformats = ch->rawwriteformat = ch->rawreadformat = fmt; + + ast_channel_set_fd(ch, 0, ast_rtp_fd(i->rtp)); + ast_channel_set_fd(ch, 1, ast_rtcp_fd(i->rtp)); + ast_channel_set_fd(ch, 5, ast_udptl_fd(i->udptl)); + if (state == AST_STATE_RING) ch->rings = 1; ch->adsicpe = AST_ADSI_UNAVAILABLE; - ch->writeformat = fmt; - ch->rawwriteformat = fmt; - ch->readformat = fmt; - ch->rawreadformat = fmt; + if (capability) + fmt = ast_best_codec(capability); + ast_set_write_format(ch, fmt); + ast_set_read_format(ch, fmt); ch->tech_pvt = i; i->owner = ch; @@ -283,6 +354,13 @@ if (i->dtmfmode & H323_DTMF_INBAND) { i->vad = ast_dsp_new(); ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT); + ast_dsp_set_features(i->vad, + DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT); + ast_dsp_set_faxmode(i->vad, + DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED); + + if (i->dtmfmode & H323_DTMF_INBANDRELAX) + ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); } ast_mutex_lock(&usecnt_lock); @@ -296,15 +374,8 @@ ast_copy_string(ch->exten, i->exten, sizeof(ch->exten)); ch->priority = 1; - if (i->callerid_name) { - ch->cid.cid_name = strdup(i->callerid_name); - } - if (i->callerid_num) { - - ch->cid.cid_num = strdup(i->callerid_num); - } - if (!ast_test_flag(i, H323_OUTGOING)) { + if(!ast_test_flag(i, H323_OUTGOING)) { if (!ast_strlen_zero(i->caller_h323id)) { pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id); @@ -331,19 +402,21 @@ ast_setstate(ch, state); if (state != AST_STATE_DOWN) { - if (ast_pbx_start(ch)) { + if (ast_pbx_start(ch)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); - ast_channel_unlock(ch); + ast_channel_unlock(ch); ast_hangup(ch); ch = NULL; - } - } + } + } + + manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\n" + "CallRef: %d\r\n", ch->name, "OOH323", i->call_reference); } else ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); - if (ch) - ast_channel_unlock(ch); + if(ch) ast_channel_unlock(ch); if (gH323Debug) ast_verbose("+++ h323_new\n"); @@ -368,6 +441,7 @@ ast_mutex_init(&pvt->lock); ast_mutex_lock(&pvt->lock); + if (!inet_aton(gIP, &ipAddr)) { ast_log(LOG_ERROR, "Invalid OOH323 driver ip address\n"); ast_mutex_unlock(&pvt->lock); @@ -376,6 +450,7 @@ return NULL; } + if (!(pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr))) { ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); @@ -387,6 +462,19 @@ ast_rtp_setqos(pvt->rtp, gTOS, 0, "ooh323"); + if (!(pvt->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, ipAddr))) { + ast_log(LOG_WARNING, "Unable to create UDPTL session: %s\n", + strerror(errno)); + ast_mutex_unlock(&pvt->lock); + ast_mutex_destroy(&pvt->lock); + free(pvt); + return NULL; + } + + ast_udptl_set_error_correction_scheme(pvt->udptl, UDPTL_ERROR_CORRECTION_NONE); + pvt->faxmode = 0; + pvt->t38support = gT38Support; + pvt->call_reference = callref; if (callToken) pvt->callToken = strdup(callToken); @@ -398,6 +486,7 @@ pvt->dtmfmode = gDTMFMode; ast_copy_string(pvt->context, gContext, sizeof(pvt->context)); ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode)); + pvt->amaflags = gAMAFLAGS; pvt->capability = gCapability; memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs)); @@ -420,7 +509,8 @@ Possible data values - peername, exten/peername, exten@ip */ static struct ast_channel *ooh323_request(const char *type, int format, - void *data, int *cause) + void *data, int *cause) + { struct ast_channel *chan = NULL; struct ooh323_pvt *p = NULL; @@ -455,14 +545,16 @@ /* This is an outgoing call, since ooh323_request is called */ ast_set_flag(p, H323_OUTGOING); - ast_copy_string(tmp, data, sizeof(data)); + + ast_copy_string(tmp, data, sizeof(tmp)); dest = strchr(tmp, '/'); if (dest) { *dest = '\0'; dest++; - ext = tmp; + ext = dest; + dest = tmp; } else if ((dest = strchr(tmp, '@'))) { *dest = '\0'; dest++; @@ -492,22 +584,20 @@ p->host = strdup(peer->ip); p->port = peer->port; /* Disable gk as we are going to call a known peer*/ - OO_SETFLAG(p->flags, H323_DISABLEGK); + /* OO_SETFLAG(p->flags, H323_DISABLEGK); */ if (ext) ast_copy_string(p->exten, ext, sizeof(p->exten)); - if (peer->capability & format) { - p->capability = peer->capability & format; - } else { - p->capability = peer->capability; - } + p->capability = peer->capability; memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref)); - p->dtmfmode = peer->dtmfmode; + p->dtmfmode |= peer->dtmfmode; + p->t38support = peer->t38support; ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode)); p->amaflags = peer->amaflags; } else { p->dtmfmode = gDTMFMode; + p->t38support = gT38Support; p->capability = gCapability; memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref)); @@ -523,7 +613,7 @@ } - chan = ooh323_new(p, AST_STATE_DOWN, p->username); + chan = ooh323_new(p, AST_STATE_DOWN, p->username, format); ast_mutex_unlock(&p->lock); @@ -531,6 +621,22 @@ ast_mutex_lock(&iflock); ooh323_destroy(p); ast_mutex_unlock(&iflock); + } else { + ast_mutex_lock(&p->lock); + p->callToken = (char*)malloc(AST_MAX_EXTENSION); + if(!p->callToken) { + ast_mutex_unlock(&p->lock); + ast_mutex_lock(&iflock); + ooh323_destroy(p); + ast_mutex_unlock(&iflock); + ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n"); + return NULL; /* TODO: need to clean/hangup?? */ + } + + ast_mutex_unlock(&p->lock); + ast_mutex_lock(&ooh323c_cmd_lock); + ooMakeCall(data, p->callToken, AST_MAX_EXTENSION, NULL); + ast_mutex_unlock(&ooh323c_cmd_lock); } restart_monitor(); @@ -569,9 +675,10 @@ struct ooh323_user *user; if (gH323Debug) - ast_verbose("--- find_user\n"); + ast_verbose("--- find_user: %s, %s\n",name,ip); ast_mutex_lock(&userl.lock); + for (user = userl.users; user; user = user->next) { if (ip && user->mUseIP && !strcmp(user->mIP, ip)) { break; @@ -580,6 +687,7 @@ break; } } + ast_mutex_unlock(&userl.lock); if (gH323Debug) @@ -627,6 +735,7 @@ if (gH323Debug) ast_verbose("--- find_peer \"%s\"\n", name); + ast_mutex_lock(&peerl.lock); for (peer = peerl.peers; peer; peer = peer->next) { if (gH323Debug) { @@ -670,16 +779,24 @@ return -1; } ast_mutex_lock(&p->lock); - if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) { + if (digit == 'e' && !p->faxmode && p->t38support != T38_DISABLED) { + if (!p->chmodepend) { + if (gH323Debug) + ast_verbose("request to change %s to t.38 because fax cng\n", + p->callToken); + p->chmodepend = 1; + ooRequestChangeMode(p->callToken, 1); + } + } else if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) { ast_rtp_senddigit_begin(p->rtp, digit); } else if (((p->dtmfmode & H323_DTMF_Q931) || (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) || (p->dtmfmode & H323_DTMF_H245SIGNAL))) { dtmf[0] = digit; dtmf[1] = '\0'; - ast_mutex_lock(&ooh323c_cmd_lock); + /* ast_mutex_lock(&ooh323c_cmd_lock); */ ooSendDTMFDigit(p->callToken, dtmf); - ast_mutex_unlock(&ooh323c_cmd_lock); + /* ast_mutex_unlock(&ooh323c_cmd_lock); */ } ast_mutex_unlock(&p->lock); if (gH323Debug) @@ -715,18 +832,21 @@ { struct ooh323_pvt *p = ast->tech_pvt; char destination[256]; - int res = 0; + int res=0, i; const char *val = NULL; ooCallOptions opts = { .fastStart = TRUE, .tunneling = TRUE, .disableGk = TRUE, - .callMode = OO_CALLMODE_AUDIOCALL + .callMode = OO_CALLMODE_AUDIOCALL, + .transfercap = 0 }; if (gH323Debug) ast_verbose("--- ooh323_call- %s\n", dest); - if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { + + if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) + { ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor " "reserved\n", ast->name); return -1; @@ -734,23 +854,18 @@ ast_mutex_lock(&p->lock); ast_set_flag(p, H323_OUTGOING); if (ast->cid.cid_num) { - if (p->callerid_num) { - free(p->callerid_num); - } + if(p->callerid_num) free(p->callerid_num); p->callerid_num = strdup(ast->cid.cid_num); } if (ast->cid.cid_name) { - if (p->callerid_name) { - free(p->callerid_name); - } - p->callerid_name = strdup(ast->cid.cid_name); + if(p->callerid_name) free(p->callerid_name); + p->callerid_name = strdup(ast->cid.cid_name); } else{ ast->cid.cid_name = strdup(gCallerID); - if (p->callerid_name) { + if(p->callerid_name) free(p->callerid_name); - } p->callerid_name = strdup(ast->cid.cid_name); } @@ -763,9 +878,8 @@ if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) { ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits)); - if (!p->callerid_num) { + if(!p->callerid_num) p->callerid_num = strdup(val); - } } if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) { @@ -776,13 +890,6 @@ ast_copy_string(p->caller_url, val, sizeof(p->caller_url)); } - - if (!(p->callToken = (char*)malloc(AST_MAX_EXTENSION))) { - ast_mutex_unlock(&p->lock); - ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n"); - return -1; /* TODO: need to clean/hangup?? */ - } - if (p->host && p->port != 0) snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port); else if (p->host) @@ -790,17 +897,27 @@ else ast_copy_string(destination, dest, sizeof(destination)); - ast_mutex_lock(&ooh323c_cmd_lock); - if (OO_TESTFLAG(p->flags, H323_DISABLEGK)) - res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, &opts); - else - res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, NULL); - ast_mutex_unlock(&ooh323c_cmd_lock); + destination[sizeof(destination)-1]='\0'; + + opts.transfercap = ast->transfercapability; + + if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) { + + for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000); + + res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, &opts); + + } else { + + for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000); + + res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, NULL); + } ast_mutex_unlock(&p->lock); if (res != OO_OK) { ast_log(LOG_ERROR, "Failed to make call\n"); - return -1; /* TODO: cleanup */ + return -1; /* ToDO: cleanup */ } if (gH323Debug) ast_verbose("+++ ooh323_call\n"); @@ -811,6 +928,7 @@ static int ooh323_hangup(struct ast_channel *ast) { struct ooh323_pvt *p = ast->tech_pvt; + int q931cause = AST_CAUSE_NORMAL_CLEARING; if (gH323Debug) ast_verbose("--- ooh323_hangup\n"); @@ -818,19 +936,39 @@ if (p) { ast_mutex_lock(&p->lock); + if (ast->hangupcause) { + q931cause = ast->hangupcause; + } else { + const char *cause = pbx_builtin_getvar_helper(ast, "DIALSTATUS"); + if (cause) { + if (!strcmp(cause, "CONGESTION")) { + q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION; + } else if (!strcmp(cause, "BUSY")) { + q931cause = AST_CAUSE_USER_BUSY; + } else if (!strcmp(cause, "CHANISUNVAIL")) { + q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; + } else if (!strcmp(cause, "NOANSWER")) { + q931cause = AST_CAUSE_NO_ANSWER; + } else if (!strcmp(cause, "CANCEL")) { + q931cause = AST_CAUSE_CALL_REJECTED; + } + } + } + + + if (gH323Debug) - ast_verbose(" hanging %s\n", p->username); + ast_verbose(" hanging %s with cause: %d\n", p->username, q931cause); ast->tech_pvt = NULL; if (!ast_test_flag(p, H323_ALREADYGONE)) { ast_mutex_lock(&ooh323c_cmd_lock); - ooHangCall(p->callToken, - ooh323_convert_hangupcause_asteriskToH323(p->owner->hangupcause)); + ooHangCall(p->callToken, + ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause); ast_mutex_unlock(&ooh323c_cmd_lock); ast_set_flag(p, H323_ALREADYGONE); /* ast_mutex_unlock(&p->lock); */ - } else { + } else ast_set_flag(p, H323_NEEDDESTROY); - } /* detach channel here */ if (p->owner) { p->owner->tech_pvt = NULL; @@ -847,7 +985,7 @@ } else { ast_log(LOG_ERROR, "No call to hangup\n" ); - return -1; + /* return -1; */ } if (gH323Debug) @@ -863,17 +1001,21 @@ if (gH323Debug) ast_verbose("--- ooh323_answer\n"); - ast_mutex_lock(&p->lock); - if (ast->_state != AST_STATE_UP) { - ast_channel_lock(ast); - ast_setstate(ast, AST_STATE_UP); - ast_debug(1, "ooh323_answer(%s)\n", ast->name); - ast_channel_unlock(ast); - ast_mutex_lock(&ooh323c_cmd_lock); - ooAnswerCall(p->callToken); - ast_mutex_unlock(&ooh323c_cmd_lock); + if (p) { + + ast_mutex_lock(&p->lock); + if (ast->_state != AST_STATE_UP) { + ast_channel_lock(ast); + ast_setstate(ast, AST_STATE_UP); + if (option_debug) + ast_debug(1, "ooh323_answer(%s)\n", ast->name); + ast_channel_unlock(ast); + /* ast_mutex_lock(&ooh323c_cmd_lock); */ + ooAnswerCall(p->callToken); + /* ast_mutex_unlock(&ooh323c_cmd_lock); */ + } + ast_mutex_unlock(&p->lock); } - ast_mutex_unlock(&p->lock); if (gH323Debug) ast_verbose("+++ ooh323_answer\n"); @@ -887,6 +1029,8 @@ static struct ast_frame null_frame = { AST_FRAME_NULL, }; struct ooh323_pvt *p = ast->tech_pvt; + if (!p) return &null_frame; + ast_mutex_lock(&p->lock); if (p->rtp) fr = ooh323_rtp_read(ast, p); @@ -901,27 +1045,100 @@ { struct ooh323_pvt *p = ast->tech_pvt; int res = 0; + char *callToken = (char *)NULL; + int16_t* t38data; + int t38samples; + + if (p) { + ast_mutex_lock(&p->lock); + + if (f->frametype == AST_FRAME_MODEM) { + ast_debug(1, "Send UDPTL %d/%d len %d for %s\n", + f->frametype, f->subclass, f->datalen, ast->name); + if (p->udptl) + res = ast_udptl_write(p->udptl, f); + ast_mutex_unlock(&p->lock); + return res; + } + + + if (f->frametype == AST_FRAME_VOICE) { +/* sending progress for first */ + if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent) { + callToken = (p->callToken ? strdup(p->callToken) : NULL); + ooManualProgress(callToken); + p->progsent = 1; + free(callToken); + } + + +/* if we are in fax t30-t38 transparent mode */ - if (f->frametype == AST_FRAME_VOICE) { - if (!(f->subclass & ast->nativeformats)) { - ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native " - "formats is %d (read/write = %d/%d)\n", - f->subclass, ast->nativeformats, ast->readformat, + if (p->faxmode && p->t38support == T38_TRANSPARENT) { + if (f->subclass == AST_FORMAT_SLINEAR) { + t38data = f->data.ptr; + t38samples = f->samples; + } else { + t38samples = 0; + ast_verbose("Got non-slin frame for %s in transparent fax mode\n", + ast->name); + ast_set_write_format(ast, AST_FORMAT_SLINEAR); + ast_set_read_format(ast, AST_FORMAT_SLINEAR); + ast_mutex_unlock(&p->lock); + return 0; + } + + if (t38samples) { + t38_gateway_rx(&p->t38r_state, t38data, t38samples); + if (gH323Debug) + ast_debug(4, "t38gw_rx %d\n", t38samples); + } + + res = f->samples; + time_t ct = time(NULL); + if (ct - p->lastTxT38 > T38TOAUDIOTIMEOUT && !p->chmodepend) { + if (gH323Debug) + ast_verbose("request to change %s to audio because" + "t38 timeout\n", ast->name); + ooRequestChangeMode(p->callToken, 0); + p->chmodepend = 1; + } + ast_mutex_unlock(&p->lock); + return res; + } + + + if (!(f->subclass & ast->nativeformats)) { + if (ast->nativeformats != 0) { + ast_log(LOG_WARNING, "Asked to transmit frame type %d," + " while native " + "formats is %d (read/write = %d/%d)\n", + f->subclass, ast->nativeformats, ast->readformat, ast->writeformat); + ast_set_write_format(ast, f->subclass); + } else { + /* ast_set_write_format(ast, f->subclass); + ast->nativeformats = f->subclass; */ + } + ast_mutex_unlock(&p->lock); return 0; - } - if (p) { - ast_mutex_lock(&p->lock); - if (p->rtp) - res = ast_rtp_write(p->rtp, f); + } + + if (p->rtp) + res = ast_rtp_write(p->rtp, f); + + ast_mutex_unlock(&p->lock); + + } else if (f->frametype == AST_FRAME_IMAGE) { ast_mutex_unlock(&p->lock); - } - } else if (f->frametype == AST_FRAME_IMAGE) { - return 0; - } else { - ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", + return 0; + } else { + ast_log(LOG_WARNING, "Can't send %d type frames with OOH323 write\n", f->frametype); - return 0; + ast_mutex_unlock(&p->lock); + return 0; + } + } return res; @@ -933,6 +1150,8 @@ struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt; char *callToken = (char *)NULL; + if (!p) return -1; + ast_mutex_lock(&p->lock); callToken = (p->callToken ? strdup(p->callToken) : NULL); ast_mutex_unlock(&p->lock); @@ -946,12 +1165,12 @@ if (gH323Debug) ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken); - + ast_mutex_lock(&p->lock); switch (condition) { case AST_CONTROL_CONGESTION: if (!ast_test_flag(p, H323_ALREADYGONE)) { ast_mutex_lock(&ooh323c_cmd_lock); - ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED); + ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, AST_CAUSE_SWITCH_CONGESTION); ast_mutex_unlock(&ooh323c_cmd_lock); ast_set_flag(p, H323_ALREADYGONE); } @@ -959,7 +1178,7 @@ case AST_CONTROL_BUSY: if (!ast_test_flag(p, H323_ALREADYGONE)) { ast_mutex_lock(&ooh323c_cmd_lock); - ooHangCall(callToken, OO_REASON_LOCAL_BUSY); + ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY); ast_mutex_unlock(&ooh323c_cmd_lock); ast_set_flag(p, H323_ALREADYGONE); } @@ -970,9 +1189,68 @@ case AST_CONTROL_UNHOLD: ast_moh_stop(ast); break; - case AST_CONTROL_PROCEEDING: - case AST_CONTROL_RINGING: case AST_CONTROL_PROGRESS: + if (!p->progsent) { + /* ast_mutex_lock(&ooh323c_cmd_lock); */ + if (gH323Debug) + ast_log(LOG_DEBUG,"Sending manual progress for %s, res = %d\n", callToken, + ooManualProgress(callToken)); else + ooManualProgress(callToken); + p->progsent = 1; + /* ast_mutex_unlock(&ooh323c_cmd_lock); */ + } + break; + case AST_CONTROL_RINGING: + /* ast_mutex_lock(&ooh323c_cmd_lock); */ + if (gH323Debug) + ast_log(LOG_DEBUG,"Sending manual ringback for %s, res = %d\n", callToken, + ooManualRingback(callToken)); else + ooManualRingback(callToken); + /* ast_mutex_unlock(&ooh323c_cmd_lock); */ + break; + case AST_CONTROL_SRCUPDATE: + ast_rtp_new_source(p->rtp); + break; + + case AST_CONTROL_T38: + if (p->t38support != T38_FAXGW) { + enum ast_control_t38 message = AST_T38_REFUSED; + ast_queue_control_data(ast, AST_CONTROL_T38, &message, sizeof(message)); + break; + } + if (datalen != sizeof(enum ast_control_t38)) { + ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. " + "Expected %d, got %d\n", + (int)sizeof(enum ast_control_t38), (int)datalen); + } else { + enum ast_control_t38* message = (enum ast_control_t38*) data; + switch (*message) { + + case AST_T38_REQUEST_NEGOTIATE: + + if (!p->chmodepend && !p->faxmode) { + ooRequestChangeMode(p->callToken, 1); + p->chmodepend = 1; + } + break; + + case AST_T38_REQUEST_TERMINATE: + + if (!p->chmodepend && p->faxmode) { + ooRequestChangeMode(p->callToken, 0); + p->chmodepend = 1; + } + break; + + + default: + ; + + } + + } + break; + case AST_CONTROL_PROCEEDING: case -1: break; default: @@ -980,13 +1258,65 @@ condition, callToken); } + ast_mutex_unlock(&p->lock); + if (gH323Debug) ast_verbose("++++ ooh323_indicate %d on %s\n", condition, callToken); - + free(callToken); return -1; } +static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen) +{ + + struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt; + int res = -1; + enum ast_t38_state state = T38_STATE_UNAVAILABLE; + char* cp; + + if (!p) return -1; + + ast_mutex_lock(&p->lock); + + if (gH323Debug) + ast_verbose("----- ooh323_queryoption %d on channel %s\n", option, ast->name); + + switch (option) { + + case AST_OPTION_T38_STATE: + + if (*datalen != sizeof(enum ast_t38_state)) { + ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option." + " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); + break; + } + if (p->t38support != T38_DISABLED) + state = T38_STATE_UNKNOWN; + if (p->faxmode) + state = (p->chmodepend) ? T38_STATE_UNKNOWN : T38_STATE_NEGOTIATED; + else if (p->chmodepend) + state = T38_STATE_NEGOTIATING; + + + *((enum ast_t38_state *) data) = state; + res = 0; + break; + + default: ; + + } + + if (gH323Debug) + ast_verbose("+++++ ooh323_queryoption %d on channel %s\n", option, ast->name); + + ast_mutex_unlock(&p->lock); + + return res; +} + + + static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) { struct ooh323_pvt *p = newchan->tech_pvt; @@ -1018,13 +1348,12 @@ void ooh323_set_write_format(ooCallData *call, int fmt) { -#if 0 struct ooh323_pvt *p = NULL; char formats[512]; -#ifdef print_debug - printf("--- ooh323_update_writeformat %s\n", - ast_getformatname_multiple(formats,512, fmt)); -#endif + + if (gH323Debug) + ast_verbose("--- ooh323_update_writeformat %s\n", + ast_getformatname_multiple(formats,512, fmt)); p = find_call(call); if (!p) { @@ -1035,34 +1364,46 @@ ast_mutex_lock(&p->lock); p->writeformat = fmt; - ast_mutex_unlock(&p->lock); if (p->owner) { - printf("Writeformat before update %s\n", - ast_getformatname_multiple(formats,512, p->owner->writeformat)); - ast_set_write_format(p->owner, fmt); - } - else - ast_log(LOG_ERROR, "No owner found\n"); + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + if (gH323Debug) + ast_verbose("Writeformat before update %s/%s\n", + ast_getformatname_multiple(formats,512, p->owner->writeformat), + ast_getformatname_multiple(formats,512, p->owner->nativeformats)); + p->owner->nativeformats = fmt; + ast_set_write_format(p->owner, p->owner->writeformat); + ast_set_read_format(p->owner, p->owner->readformat); + ast_channel_unlock(p->owner); + } else + ast_log(LOG_ERROR, "No owner found\n"); -#ifdef print_debug - printf("+++ ooh323_update_writeformat\n"); -#endif -#endif -} + ast_mutex_unlock(&p->lock); + if (gH323Debug) + ast_verbose("+++ ooh323_update_writeformat\n"); +} void ooh323_set_read_format(ooCallData *call, int fmt) { -#if 0 struct ooh323_pvt *p = NULL; char formats[512]; -#ifdef print_debug - printf("--- ooh323_update_readformat %s\n", - ast_getformatname_multiple(formats,512, fmt)); -#endif + if (gH323Debug) + ast_verbose("--- ooh323_update_readformat %s\n", + ast_getformatname_multiple(formats,512, fmt)); + p = find_call(call); if (!p) { ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken); @@ -1070,16 +1411,39 @@ } ast_mutex_lock(&p->lock); + p->readformat = fmt; + + + if (p->owner) { + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + + if (gH323Debug) + ast_verbose("Readformat before update %s\n", + ast_getformatname_multiple(formats,512, p->owner->readformat)); + p->owner->nativeformats = fmt; + ast_set_read_format(p->owner, p->owner->readformat); + ast_channel_unlock(p->owner); + } else + ast_log(LOG_ERROR, "No owner found\n"); + ast_mutex_unlock(&p->lock); - ast_set_read_format(p->owner, fmt); - -#ifdef print_debug - printf("+++ ooh323_update_readformat\n"); -#endif -#endif + + if (gH323Debug) + ast_verbose("+++ ooh323_update_readformat\n"); } + int onAlerting(ooCallData *call) { struct ooh323_pvt *p = NULL; @@ -1088,35 +1452,85 @@ if (gH323Debug) ast_verbose("--- onAlerting %s\n", call->callToken); - if (!(p = find_call(call))) { + p = find_call(call); + + if(!p) { ast_log(LOG_ERROR, "No matching call found\n"); return -1; } ast_mutex_lock(&p->lock); - if (!ast_test_flag(p, H323_OUTGOING)) { - if (!(c = ooh323_new(p, AST_STATE_RING, p->username))) { - ast_mutex_unlock(&p->lock); - ast_log(LOG_ERROR, "Could not create ast_channel\n"); - return -1; - } + if (!p->owner) { ast_mutex_unlock(&p->lock); - } else { - if (!p->owner) { - ast_mutex_unlock(&p->lock); - ast_log(LOG_ERROR, "Channel has no owner\n"); - return 0; - } - c = p->owner; + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); ast_mutex_unlock(&p->lock); - ast_channel_lock(c); - ast_setstate(c, AST_STATE_RINGING); - ast_channel_unlock(c); - ast_queue_control(c, AST_CONTROL_RINGING); + usleep(1); + ast_mutex_lock(&p->lock); } - - if (gH323Debug) - ast_verbose("+++ onAlerting %s\n", call->callToken); - + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + c = p->owner; + if (c->_state != AST_STATE_UP) + ast_setstate(c, AST_STATE_RINGING); + + ast_queue_control(c, AST_CONTROL_RINGING); + ast_channel_unlock(c); + ast_mutex_unlock(&p->lock); + + if (gH323Debug) + ast_verbose("+++ onAlerting %s\n", call->callToken); + + return OO_OK; +} + +int onProgress(ooCallData *call) +{ + struct ooh323_pvt *p = NULL; + struct ast_channel *c = NULL; + + if (gH323Debug) + ast_verbose("--- onProgress %s\n", call->callToken); + + p = find_call(call); + + if(!p) { + ast_log(LOG_ERROR, "No matching call found\n"); + return -1; + } + ast_mutex_lock(&p->lock); + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + c = p->owner; + if (c->_state != AST_STATE_UP) + ast_setstate(c, AST_STATE_RINGING); + + ast_queue_control(c, AST_CONTROL_PROGRESS); + ast_channel_unlock(c); + ast_mutex_unlock(&p->lock); + + if (gH323Debug) + ast_verbose("+++ onProgress %s\n", call->callToken); + return OO_OK; } @@ -1150,8 +1564,21 @@ f.data.ptr = NULL; f.mallocd = 0; f.src = "SEND_DIGIT"; - ast_mutex_unlock(&p->lock); + + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } res = ast_queue_frame(p->owner, &f); + ast_channel_unlock(p->owner); + ast_mutex_unlock(&p->lock); return res; } @@ -1159,6 +1586,7 @@ { struct ooh323_pvt *p = NULL; struct ooh323_user *user = NULL; + struct ast_channel *c = NULL; ooAliases *alias = NULL; char *at = NULL; char number [OO_MAX_NUMBER_LENGTH]; @@ -1190,30 +1618,35 @@ p->callerid_name = strdup(alias->value); } ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id)); - } else if (alias->type == T_H225AliasAddress_dialedDigits) { - if (!p->callerid_num) { - p->callerid_num = strdup(alias->value); } + else if(alias->type == T_H225AliasAddress_dialedDigits) + { + if(!p->callerid_num) + p->callerid_num = strdup(alias->value); ast_copy_string(p->caller_dialedDigits, alias->value, sizeof(p->caller_dialedDigits)); - } else if (alias->type == T_H225AliasAddress_email_ID) { + } + else if(alias->type == T_H225AliasAddress_email_ID) + { ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email)); - } else if (alias->type == T_H225AliasAddress_url_ID) { + } + else if(alias->type == T_H225AliasAddress_url_ID) + { ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url)); } } } number[0] = '\0'; - if (ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) { - ast_copy_string(p->exten, number, sizeof(p->exten)); - } else { + if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) { + strncpy(p->exten, number, sizeof(p->exten)-1); + } else { update_our_aliases(call, p); if (!ast_strlen_zero(p->callee_dialedDigits)) { - ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten)); - } else if (!ast_strlen_zero(p->callee_h323id)) { + ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten)); + } else if(!ast_strlen_zero(p->callee_h323id)) { ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten)); - } else if (!ast_strlen_zero(p->callee_email)) { + } else if(!ast_strlen_zero(p->callee_email)) { ast_copy_string(p->exten, p->callee_email, sizeof(p->exten)); if ((at = strchr(p->exten, '@'))) { *at = '\0'; @@ -1223,34 +1656,62 @@ /* if no extension found, set to default 's' */ if (ast_strlen_zero(p->exten)) { - ast_copy_string(p->exten, "s", sizeof(p->exten)); + p->exten[0]='s'; + p->exten[1]='\0'; } - if (!p->callerid_name) { + /* May there isn't needed to setup ip as name */ + /* if (!p->callerid_name) { p->callerid_name = strdup(call->remoteIP); } - if (p->callerid_name) { - if ((user = find_user(p->callerid_name, call->remoteIP))) { + if (p->callerid_name) { */ + user = find_user(p->callerid_name, call->remoteIP); + if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) { ast_mutex_lock(&user->lock); p->username = strdup(user->name); + p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) : + ast_strdup(user->name); ast_copy_string(p->context, user->context, sizeof(p->context)); ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode)); p->amaflags = user->amaflags; p->capability = user->capability; memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref)); - p->dtmfmode = user->dtmfmode; + p->dtmfmode |= user->dtmfmode; + p->t38support = user->t38support; /* Since, call is coming from a pbx user, no need to use gk */ - OO_SETFLAG(p->flags, H323_DISABLEGK); - OO_SETFLAG(call->flags, OO_M_DISABLEGK); + /* OO_SETFLAG(p->flags, H323_DISABLEGK); + OO_SETFLAG(call->flags, OO_M_DISABLEGK); */ + if (user->incominglimit) user->inUse++; ast_mutex_unlock(&user->lock); - } + } else { + if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) { + p->username = strdup(call->remoteIP); + } else { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP); + ast_mutex_lock(&ooh323c_cmd_lock); + if (!user) + ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED); + else + ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION); + ast_mutex_unlock(&ooh323c_cmd_lock); + ast_set_flag(p, H323_NEEDDESTROY); + return -1; + } } +/* } */ - - ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode); + ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode, p->t38support); configure_local_rtp(p, call); +/* Incoming call */ + c = ooh323_new(p, AST_STATE_RING, p->username, 0); + if(!c) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Could not create ast_channel\n"); + return -1; + } ast_mutex_unlock(&p->lock); if (gH323Debug) @@ -1262,38 +1723,105 @@ +int onOutgoingCall(ooCallData *call) +{ + struct ooh323_pvt *p = NULL; + int i = 0; + + if (gH323Debug) + ast_verbose("--- onOutgoingCall %lx: %s\n", call, call->callToken); + + if (!strcmp(call->callType, "outgoing")) { + p = find_call(call); + if (!p) { + ast_log(LOG_ERROR, "Failed to find a matching call.\n"); + return -1; + } + ast_mutex_lock(&p->lock); + + if (!ast_strlen_zero(p->callerid_name)) { + ooCallSetCallerId(call, p->callerid_name); + } + if (!ast_strlen_zero(p->callerid_num)) { + i = 0; + while (*(p->callerid_num + i) != '\0') { + if(!isdigit(*(p->callerid_num+i))) { break; } + i++; + } + if(*(p->callerid_num+i) == '\0') + ooCallSetCallingPartyNumber(call, p->callerid_num); + else { + if(!p->callerid_name) + ooCallSetCallerId(call, p->callerid_num); + } + } + + if (!ast_strlen_zero(p->caller_h323id)) + ooCallAddAliasH323ID(call, p->caller_h323id); + + if (!ast_strlen_zero(p->caller_dialedDigits)) { + if (gH323Debug) { + ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits); + } + ooCallAddAliasDialedDigits(call, p->caller_dialedDigits); + } else if (!ast_strlen_zero(p->callerid_num)) { + if (ooIsDailedDigit(p->callerid_num)) { + if (gH323Debug) { + ast_verbose("setting callid number %s\n", p->callerid_num); + } + ooCallAddAliasDialedDigits(call, p->callerid_num); + } else if (ast_strlen_zero(p->caller_h323id)) { + ooCallAddAliasH323ID(call, p->callerid_num); + } + } + + + ast_mutex_unlock(&p->lock); + } + + if (gH323Debug) + ast_verbose("+++ onOutgoingCall %s\n", call->callToken); + return OO_OK; +} + + int onNewCallCreated(ooCallData *call) { struct ooh323_pvt *p = NULL; int i = 0; if (gH323Debug) - ast_verbose("--- onNewCallCreated %s\n", call->callToken); + ast_verbose("--- onNewCallCreated %lx: %s\n", call, call->callToken); + + ast_mutex_lock(&call->Lock); + if (ooh323c_start_call_thread(call)) { + ast_log(LOG_ERROR,"Failed to create call thread.\n"); + ast_mutex_unlock(&call->Lock); + return -1; + } if (!strcmp(call->callType, "outgoing")) { p = find_call(call); if (!p) { - ast_log(LOG_ERROR, "No matching call found for outgoing call\n"); + ast_log(LOG_ERROR, "Failed to find a matching call.\n"); return -1; } ast_mutex_lock(&p->lock); + if (p->callerid_name) { ooCallSetCallerId(call, p->callerid_name); } if (p->callerid_num) { i = 0; while (*(p->callerid_num + i) != '\0') { - if (!isdigit(*(p->callerid_num + i))) { - break; - } + if(!isdigit(*(p->callerid_num+i))) { break; } i++; } - if (*(p->callerid_num + i) == '\0') { + if(*(p->callerid_num+i) == '\0') ooCallSetCallingPartyNumber(call, p->callerid_num); - } else { - if (!p->callerid_name) { + else { + if(!p->callerid_name) ooCallSetCallerId(call, p->callerid_num); - } } } @@ -1330,17 +1858,19 @@ char prefsBuf[256]; ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf)); ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n", - p->username?p->username:"NULL", call->callToken, prefsBuf); + p->username?p->username:"NULL", call->callToken, prefsBuf); } - ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode); + ooh323c_set_capability_for_call(call, &p->prefs, p->capability, + p->dtmfmode, p->t38support); configure_local_rtp(p, call); ast_mutex_unlock(&p->lock); } + + ast_mutex_unlock(&call->Lock); if (gH323Debug) ast_verbose("+++ onNewCallCreated %s\n", call->callToken); - return OO_OK; } @@ -1351,33 +1881,35 @@ if (gH323Debug) ast_verbose("--- onCallEstablished %s\n", call->callToken); + if (!(p = find_call(call))) { ast_log(LOG_ERROR, "Failed to find a matching call.\n"); return -1; } - ast_mutex_lock(&p->lock); - if (!p->owner) { - ast_mutex_unlock(&p->lock); - ast_log(LOG_ERROR, "Channel has no owner\n"); - return -1; - } - - while (ast_channel_trylock(p->owner)) { - ast_debug(1,"Failed to grab lock, trying again\n"); - ast_mutex_unlock(&p->lock); - usleep(1); + + if(ast_test_flag(p, H323_OUTGOING)) { ast_mutex_lock(&p->lock); - } - if (p->owner->_state != AST_STATE_UP) { - ast_setstate(p->owner, AST_STATE_UP); - } - ast_channel_unlock(p->owner); - if (ast_test_flag(p, H323_OUTGOING)) { - struct ast_channel* c = p->owner; - ast_mutex_unlock(&p->lock); - ast_queue_control(c, AST_CONTROL_ANSWER); - } else { + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return -1; + } + + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (p->owner) { + struct ast_channel* c = p->owner; + ast_queue_control(c, AST_CONTROL_ANSWER); + ast_channel_unlock(p->owner); + manager_event(EVENT_FLAG_SYSTEM,"ChannelUpdate","Channel: %s\r\nChanneltype: %s\r\n" + "CallRef: %d\r\n", c->name, "OOH323", p->call_reference); + } ast_mutex_unlock(&p->lock); + } if (gH323Debug) @@ -1394,42 +1926,48 @@ if (gH323Debug) ast_verbose("--- onCallCleared %s \n", call->callToken); - p = find_call(call); - if (!p) { - return 0; - } + + if ((p = find_call(call))) { ast_mutex_lock(&p->lock); while (p->owner) { if (ast_channel_trylock(p->owner)) { ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n"); - ast_debug(1,"Failed to grab lock, trying again\n"); + ast_log(LOG_DEBUG,"Failed to grab lock, trying again\n"); ast_mutex_unlock(&p->lock); usleep(1); ast_mutex_lock(&p->lock); } else { - ownerLock = 1; - break; + ownerLock = 1; break; } } if (ownerLock) { if (!ast_test_flag(p, H323_ALREADYGONE)) { - /* NOTE: Channel is not detached yet */ ast_set_flag(p, H323_ALREADYGONE); - p->owner->hangupcause = - ooh323_convert_hangupcause_h323ToAsterisk(call->callEndReason); + p->owner->hangupcause = call->q931cause; p->owner->_softhangup |= AST_SOFTHANGUP_DEV; - ast_channel_unlock(p->owner); - ast_queue_hangup(p->owner); - ast_mutex_unlock(&p->lock); - return OO_OK; + ast_queue_hangup_with_cause(p->owner,call->q931cause); } + } + + if(p->owner) { + p->owner->tech_pvt = NULL; ast_channel_unlock(p->owner); + p->owner = NULL; } + ast_set_flag(p, H323_NEEDDESTROY); + + ooh323c_stop_call_thread(call); + ast_mutex_unlock(&p->lock); + ast_mutex_lock(&usecnt_lock); + usecnt--; + ast_mutex_unlock(&usecnt_lock); + + } if (gH323Debug) ast_verbose("+++ onCallCleared\n"); @@ -1437,7 +1975,6 @@ return OO_OK; } -#if 0 static void ooh323_delete_user(struct ooh323_user *user) { struct ooh323_user *prev = NULL, *cur = NULL; @@ -1469,7 +2006,6 @@ ast_verbose("+++ ooh323_delete_user\n"); } -#endif void ooh323_delete_peer(struct ooh323_peer *peer) { @@ -1479,36 +2015,33 @@ ast_verbose("--- ooh323_delete_peer\n"); if (peer) { + cur = peerl.peers; ast_mutex_lock(&peerl.lock); - for (cur = peerl.peers; cur; prev = cur, cur = cur->next) { - if (cur == peer) { - break; - } + while(cur) { + if(cur==peer) break; + prev = cur; + cur = cur->next; } if (cur) { - if (prev) { + if(prev) prev->next = cur->next; - } else { + else peerl.peers = cur->next; } - } ast_mutex_unlock(&peerl.lock); - if (peer->h323id) - free(peer->h323id); - if (peer->email) - free(peer->email); - if (peer->url) - free(peer->url); - if (peer->e164) - free(peer->e164); + if(peer->h323id) free(peer->h323id); + if(peer->email) free(peer->email); + if(peer->url) free(peer->url); + if(peer->e164) free(peer->e164); free(peer); } if (gH323Debug) ast_verbose("+++ ooh323_delete_peer\n"); + } @@ -1520,7 +2053,7 @@ if (gH323Debug) ast_verbose("--- build_user\n"); - user = ast_calloc(1, sizeof(*user)); + user = ast_calloc(1,sizeof(struct ooh323_user)); if (user) { ast_mutex_init(&user->lock); ast_copy_string(user->name, name, sizeof(user->name)); @@ -1528,6 +2061,7 @@ memcpy(&user->prefs, &gPrefs, sizeof(user->prefs)); user->rtptimeout = gRTPTimeout; user->dtmfmode = gDTMFMode; + user->t38support = gT38Support; /* set default context */ ast_copy_string(user->context, gContext, sizeof(user->context)); ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode)); @@ -1541,27 +2075,31 @@ if (user->incominglimit < 0) user->incominglimit = 0; } else if (!strcasecmp(v->name, "accountcode")) { - ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode)); + strncpy(user->accountcode, v->value, + sizeof(user->accountcode)-1); } else if (!strcasecmp(v->name, "rtptimeout")) { user->rtptimeout = atoi(v->value); if (user->rtptimeout < 0) user->rtptimeout = gRTPTimeout; } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&user->prefs, &user->capability, - v->value, 0); + ast_parse_allow_disallow(&user->prefs, + &user->capability, v->value, 0); } else if (!strcasecmp(v->name, "allow")) { const char* tcodecs = v->value; if (!strcasecmp(v->value, "all")) { tcodecs = "ulaw,alaw,g729,g723,gsm"; } - ast_parse_allow_disallow(&user->prefs, &user->capability, - tcodecs, 1); + ast_parse_allow_disallow(&user->prefs, + &user->capability, tcodecs, 1); } else if (!strcasecmp(v->name, "amaflags")) { user->amaflags = ast_cdr_amaflags2int(v->value); } else if (!strcasecmp(v->name, "ip")) { - ast_copy_string(user->mIP, v->value, sizeof(user->mIP)); + strncpy(user->mIP, v->value, sizeof(user->mIP)-1); + user->mUseIP = 1; + } else if (!strcasecmp(v->name, "host")) { + strncpy(user->mIP, v->value, sizeof(user->mIP)-1); user->mUseIP = 1; - } else if (!strcasecmp(v->name, "dtmfmode")) { + } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "rfc2833")) user->dtmfmode = H323_DTMF_RFC2833; else if (!strcasecmp(v->value, "q931keypad")) @@ -1570,6 +2108,21 @@ user->dtmfmode = H323_DTMF_H245ALPHANUMERIC; else if (!strcasecmp(v->value, "h245signal")) user->dtmfmode = H323_DTMF_H245SIGNAL; + else if (!strcasecmp(v->value, "inband")) + user->dtmfmode = H323_DTMF_INBAND; + } else if (!strcasecmp(v->name, "relaxdtmf")) { + user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; + } else if (!strcasecmp(v->name, "t38support")) { + if (!strcasecmp(v->value, "disabled")) + user->t38support = T38_DISABLED; + if (!strcasecmp(v->value, "no")) + user->t38support = T38_DISABLED; + else if (!strcasecmp(v->value, "faxgw")) + user->t38support = T38_FAXGW; + else if (!strcasecmp(v->value, "yes")) + user->t38support = T38_FAXGW; + else if (!strcasecmp(v->value, "transparent")) + user->t38support = T38_TRANSPARENT; } v = v->next; } @@ -1594,18 +2147,20 @@ ast_mutex_init(&peer->lock); ast_copy_string(peer->name, name, sizeof(peer->name)); peer->capability = gCapability; - memcpy(&peer->prefs, &gPrefs, sizeof(struct ast_codec_pref)); + memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs)); peer->rtptimeout = gRTPTimeout; ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode)); peer->amaflags = gAMAFLAGS; peer->dtmfmode = gDTMFMode; + peer->t38support = gT38Support; + peer->port = 1720; if (0 == friend_type) { peer->mFriend = 1; } while (v) { if (!strcasecmp(v->name, "h323id")) { - if (!(peer->h323id = ast_strdup(v->value))) { + if (!(peer->h323id = ast_strdup(v->value))) { ast_log(LOG_ERROR, "Could not allocate memory for h323id of " "peer %s\n", name); ooh323_delete_peer(peer); @@ -1636,16 +2191,18 @@ peer->port = atoi(v->value); } else if (!strcasecmp(v->name, "ip")) { ast_copy_string(peer->ip, v->value, sizeof(peer->ip)); + } else if (!strcasecmp(v->name, "host")) { + ast_copy_string(peer->ip, v->value, sizeof(peer->ip)); } else if (!strcasecmp(v->name, "outgoinglimit")) { - if ((peer->outgoinglimit = atoi(v->value)) < 0) { + peer->outgoinglimit = atoi(v->value); + if (peer->outgoinglimit < 0) peer->outgoinglimit = 0; - } } else if (!strcasecmp(v->name, "accountcode")) { ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode)); } else if (!strcasecmp(v->name, "rtptimeout")) { - if ((peer->rtptimeout = atoi(v->value)) < 0) { + peer->rtptimeout = atoi(v->value); + if(peer->rtptimeout < 0) peer->rtptimeout = gRTPTimeout; - } } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); @@ -1667,6 +2224,21 @@ peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC; else if (!strcasecmp(v->value, "h245signal")) peer->dtmfmode = H323_DTMF_H245SIGNAL; + else if (!strcasecmp(v->value, "inband")) + peer->dtmfmode = H323_DTMF_INBAND; + } else if (!strcasecmp(v->name, "relaxdtmf")) { + peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; + } else if (!strcasecmp(v->name, "t38support")) { + if (!strcasecmp(v->value, "disabled")) + peer->t38support = T38_DISABLED; + if (!strcasecmp(v->value, "no")) + peer->t38support = T38_DISABLED; + else if (!strcasecmp(v->value, "faxgw")) + peer->t38support = T38_FAXGW; + else if (!strcasecmp(v->value, "yes")) + peer->t38support = T38_FAXGW; + else if (!strcasecmp(v->value, "transparent")) + peer->t38support = T38_TRANSPARENT; } v = v->next; } @@ -1684,7 +2256,7 @@ ast_verbose("--- ooh323_do_reload\n"); } - reload_config(1); + reload_config(1); if (gH323Debug) { ast_verbose("+++ ooh323_do_reload\n"); @@ -1693,19 +2265,32 @@ return 0; } -#if 0 /*--- h323_reload: Force reload of module from cli ---*/ -static int ooh323_reload(int fd, int argc, char *argv[]) + +static char *handle_cli_ooh323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { + switch (cmd) { + case CLI_INIT: + e->command = "ooh323 reload"; + e->usage = + "Usage: ooh323 reload\n" + " Reload OOH323 config.\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (a->argc != 2) + return CLI_SHOWUSAGE; + if (gH323Debug) ast_verbose("--- ooh323_reload\n"); ast_mutex_lock(&h323_reload_lock); if (h323_reloading) { ast_verbose("Previous OOH323 reload not yet done\n"); - } - else { + } else { h323_reloading = 1; } ast_mutex_unlock(&h323_reload_lock); @@ -1716,19 +2301,16 @@ return 0; } -#endif -#if 0 static int reload(void *mod) { return ooh323_reload(0, 0, NULL); } -#endif int reload_config(int reload) { int format; - struct ooAliases *pNewAlias = NULL; + struct ooAliases *pNewAlias = NULL, *cur, *prev; struct ast_config *cfg; struct ast_variable *v; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; @@ -1752,6 +2334,17 @@ if (reload) { delete_users(); delete_peers(); + if (gH323Debug) { + ast_verbose(" reload_config - Freeing up alias list\n"); + } + cur = gAliasList; + while (cur) { + prev = cur; + cur = cur->next; + free(prev->value); + free(prev); + } + gAliasList = NULL; } /* Inintialize everything to default */ @@ -1759,9 +2352,11 @@ gPort = 1720; gIP[0] = '\0'; strcpy(gCallerID, DEFAULT_H323ID); - gCapability = AST_FORMAT_ULAW; + gCapability = AST_FORMAT_ALAW; memset(&gPrefs, 0, sizeof(struct ast_codec_pref)); gDTMFMode = H323_DTMF_RFC2833; + gT38Support = T38_FAXGW; + gTRCLVL = OOTRCLVLERR; gRasGkMode = RasNoGatekeeper; gGatekeeper[0] = '\0'; gRTPTimeout = 60; @@ -1784,7 +2379,7 @@ ast_copy_string(gIP, v->value, sizeof(gIP)); } else if (!strcasecmp(v->name, "h225portrange")) { char* endlimit = 0; - char temp[256]; + char temp[512]; ast_copy_string(temp, v->value, sizeof(temp)); endlimit = strchr(temp, ','); if (endlimit) { @@ -1793,16 +2388,12 @@ ooconfig.mTCPPortStart = atoi(temp); ooconfig.mTCPPortEnd = atoi(endlimit); - if (ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart, - ooconfig.mTCPPortEnd) == OO_FAILED) { - ast_log(LOG_ERROR, "h225portrange: Failed to set range\n"); - } } else { ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n"); } } else if (!strcasecmp(v->name, "gateway")) { gIsGateway = ast_true(v->value); - } else if (!strcasecmp(v->name, "faststart")) { + } else if (!strcasecmp(v->name, "faststart")) { gFastStart = ast_true(v->value); if (gFastStart) ooH323EpEnableFastStart(); @@ -1820,19 +2411,28 @@ ooH323EpEnableH245Tunneling(); else ooH323EpDisableH245Tunneling(); + } else if (!strcasecmp(v->name, "trybemaster")) { + gBeMaster = ast_true(v->value); + if (gBeMaster) + ooH323EpTryBeMaster(1); + else + ooH323EpTryBeMaster(0); } else if (!strcasecmp(v->name, "h323id")) { - pNewAlias = malloc(sizeof(*pNewAlias)); + pNewAlias = malloc(sizeof(struct ooAliases)); if (!pNewAlias) { ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n"); return 1; } + if (gAliasList == NULL) { /* first h323id - set as callerid if callerid is not set */ + ast_copy_string(gCallerID, v->value, sizeof(gCallerID)); + } pNewAlias->type = T_H225AliasAddress_h323_ID; pNewAlias->value = strdup(v->value); pNewAlias->next = gAliasList; gAliasList = pNewAlias; pNewAlias = NULL; } else if (!strcasecmp(v->name, "e164")) { - pNewAlias = malloc(sizeof(*pNewAlias)); + pNewAlias = malloc(sizeof(struct ooAliases)); if (!pNewAlias) { ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n"); return 1; @@ -1843,7 +2443,7 @@ gAliasList = pNewAlias; pNewAlias = NULL; } else if (!strcasecmp(v->name, "email")) { - pNewAlias = malloc(sizeof(*pNewAlias)); + pNewAlias = malloc(sizeof(struct ooAliases)); if (!pNewAlias) { ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n"); return 1; @@ -1853,6 +2453,16 @@ pNewAlias->next = gAliasList; gAliasList = pNewAlias; pNewAlias = NULL; + } else if (!strcasecmp(v->name, "t35country")) { + t35countrycode = atoi(v->value); + } else if (!strcasecmp(v->name, "t35extensions")) { + t35extensions = atoi(v->value); + } else if (!strcasecmp(v->name, "manufacturer")) { + manufacturer = atoi(v->value); + } else if (!strcasecmp(v->name, "vendorid")) { + ast_copy_string(vendor, v->value, sizeof(vendor)); + } else if (!strcasecmp(v->name, "versionid")) { + ast_copy_string(version, v->value, sizeof(version)); } else if (!strcasecmp(v->name, "callerid")) { ast_copy_string(gCallerID, v->value, sizeof(gCallerID)); } else if (!strcasecmp(v->name, "incominglimit")) { @@ -1866,13 +2476,14 @@ gRasGkMode = RasDiscoverGatekeeper; } else { gRasGkMode = RasUseSpecificGatekeeper; - ast_copy_string(gGatekeeper, v->value, sizeof(gGatekeeper)); + strncpy(gGatekeeper, v->value, sizeof(gGatekeeper)-1); } } else if (!strcasecmp(v->name, "logfile")) { - ast_copy_string(gLogFile, v->value, sizeof(gLogFile)); + strncpy(gLogFile, v->value, sizeof(gLogFile)-1); } else if (!strcasecmp(v->name, "context")) { - ast_copy_string(gContext, v->value, sizeof(gContext)); - ast_verb(3, " == Setting default context to %s\n", gContext); + strncpy(gContext, v->value, sizeof(gContext)-1); + ast_verbose(VERBOSE_PREFIX_3 " == Setting default context to %s\n", + gContext); } else if (!strcasecmp(v->name, "rtptimeout")) { gRTPTimeout = atoi(v->value); if (gRTPTimeout <= 0) @@ -1897,7 +2508,7 @@ } else if (!strcasecmp(v->name, "amaflags")) { gAMAFLAGS = ast_cdr_amaflags2int(v->value); } else if (!strcasecmp(v->name, "accountcode")) { - ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)-1); + ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)); } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0); } else if (!strcasecmp(v->name, "allow")) { @@ -1918,10 +2529,27 @@ else if (!strcasecmp(v->value, "h245signal")) gDTMFMode = H323_DTMF_H245SIGNAL; else { - 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); gDTMFMode = H323_DTMF_RFC2833; } - } + } else if (!strcasecmp(v->name, "relaxdtmf")) { + gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; + } else if (!strcasecmp(v->name, "t38support")) { + if (!strcasecmp(v->value, "disabled")) + gT38Support = T38_DISABLED; + if (!strcasecmp(v->value, "no")) + gT38Support = T38_DISABLED; + else if (!strcasecmp(v->value, "faxgw")) + gT38Support = T38_FAXGW; + else if (!strcasecmp(v->value, "yes")) + gT38Support = T38_FAXGW; + else if (!strcasecmp(v->value, "transparent")) + gT38Support = T38_TRANSPARENT; + } else if (!strcasecmp(v->name, "tracelevel")) { + gTRCLVL = atoi(v->value); + ooH323EpSetTraceLevel(gTRCLVL); + } v = v->next; } @@ -1973,8 +2601,10 @@ ast_verbose("+++ reload_config\n"); return 0; + } + static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char ip_port[30]; @@ -1994,11 +2624,12 @@ if (a->argc != 4) return CLI_SHOWUSAGE; + ast_mutex_lock(&peerl.lock); peer = peerl.peers; while (peer) { ast_mutex_lock(&peer->lock); - if (!strcmp(peer->name, a->argv[3])) + if(!strcmp(peer->name, a->argv[3])) break; else { prev = peer; @@ -2008,32 +2639,45 @@ } if (peer) { - snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port); - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &peer->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + sprintf(ip_port, "%s:%d", peer->ip, peer->port); + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &peer->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (peer->dtmfmode & H323_DTMF_RFC2833) - ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%s\n", "rfc2833"); else if (peer->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); + ast_cli(a->fd, "%s\n", "q931keypad"); else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); + ast_cli(a->fd, "%s\n", "h245alphanumeric"); else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); + ast_cli(a->fd, "%s\n", "h245signal"); + else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) + ast_cli(a->fd, "%s\n", "inband-relaxed"); + else if (peer->dtmfmode & H323_DTMF_INBAND) + ast_cli(a->fd, "%s\n", "inband"); else - ast_cli(a->fd, "%s\n", "unknown"); - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", + ast_cli(a->fd, "%s\n", "unknown"); + + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (peer->t38support == T38_DISABLED) + ast_cli(a->fd, "%s\n", "disabled"); + else if (peer->t38support == T38_TRANSPARENT) + ast_cli(a->fd, "%s\n", "audio-transparent"); + else if (peer->t38support == T38_FAXGW) + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(peer->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "Ip:Port: ", ip_port); - ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); + ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port); + ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); ast_mutex_unlock(&peer->lock); } else { - ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&peerl.lock); @@ -2042,10 +2686,9 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - char ip_port[30]; - char formats[512]; struct ooh323_peer *prev = NULL, *peer = NULL; - + char formats[512]; + char ip_port[30]; #define FORMAT "%-15.15s %-15.15s %-23.23s %-s\n" switch (cmd) { @@ -2062,25 +2705,24 @@ if (a->argc != 3) return CLI_SHOWUSAGE; - ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats"); + ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats"); ast_mutex_lock(&peerl.lock); peer = peerl.peers; while (peer) { ast_mutex_lock(&peer->lock); snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port); - ast_cli(a->fd, FORMAT, peer->name, + ast_cli(a->fd, FORMAT, peer->name, peer->accountcode, ip_port, - ast_getformatname_multiple(formats, sizeof(formats), peer->capability)); + ast_getformatname_multiple(formats,512,peer->capability)); prev = peer; peer = peer->next; ast_mutex_unlock(&prev->lock); + } ast_mutex_unlock(&peerl.lock); - #undef FORMAT - return CLI_SUCCESS; } @@ -2120,13 +2762,14 @@ if (a->argc != 4) return CLI_SHOWUSAGE; + ast_mutex_lock(&userl.lock); user = userl.users; while (user) { ast_mutex_lock(&user->lock); - if (!strcmp(user->name, a->argv[3])) + if(!strcmp(user->name, a->argv[3])) { break; - else { + } else { prev = user; user = user->next; ast_mutex_unlock(&prev->lock); @@ -2134,30 +2777,45 @@ } if (user) { - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &user->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &user->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (user->dtmfmode & H323_DTMF_RFC2833) - ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%s\n", "rfc2833"); else if (user->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); + ast_cli(a->fd, "%s\n", "q931keypad"); else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); + ast_cli(a->fd, "%s\n", "h245alphanumeric"); else if (user->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); + ast_cli(a->fd, "%s\n", "h245signal"); + else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) + ast_cli(a->fd, "%s\n", "inband-relaxed"); + else if (user->dtmfmode & H323_DTMF_INBAND) + ast_cli(a->fd, "%s\n", "inband"); else - ast_cli(a->fd, "%s\n", "unknown"); - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(user->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); - ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); + ast_cli(a->fd, "%s\n", "unknown"); + + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (user->t38support == T38_DISABLED) + ast_cli(a->fd, "%s\n", "disabled"); + else if (user->t38support == T38_TRANSPARENT) + ast_cli(a->fd, "%s\n", "audio-transparent"); + else if (user->t38support == T38_FAXGW) + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", + ast_cdr_flags2str(user->amaflags)); + ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); + ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); + ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); ast_mutex_unlock(&user->lock); } else { - ast_cli(a->fd, "User %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "User %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&userl.lock); @@ -2166,9 +2824,8 @@ static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - char formats[512]; struct ooh323_user *prev = NULL, *user = NULL; - + char formats[512]; #define FORMAT1 "%-15.15s %-15.15s %-15.15s %-s\n" switch (cmd) { @@ -2185,24 +2842,26 @@ if (a->argc != 3) return CLI_SHOWUSAGE; - ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats"); + + ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats"); ast_mutex_lock(&userl.lock); user = userl.users; - while (user) { + while(user) + { ast_mutex_lock(&user->lock); - ast_cli(a->fd, FORMAT1, user->name, + ast_cli(a->fd, FORMAT1, user->name, user->accountcode, user->context, ast_getformatname_multiple(formats, 512, user->capability)); prev = user; user = user->next; ast_mutex_unlock(&prev->lock); + } ast_mutex_unlock(&userl.lock); - #undef FORMAT1 + return RESULT_SUCCESS; - return CLI_SUCCESS; } static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) @@ -2255,25 +2914,27 @@ if (a->argc != 3) return CLI_SHOWUSAGE; + + + ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); snprintf(value, sizeof(value), "%s:%d", gIP, gPort); - ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); - ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); - ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); - ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); + ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", + ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd); + ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); + ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", + gMediaWaitForConnect?"yes":"no"); -#if 0 - { +#if (0) extern OOH323EndPoint gH323ep; - - ast_cli(a->fd, "%-20s%s\n", "FASTSTART", + ast_cli(a->fd, "%-20s%s\n", "FASTSTART", (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "TUNNELING", + ast_cli(a->fd, "%-20s%s\n", "TUNNELING", (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", + ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no"); - } #endif if (gRasGkMode == RasNoGatekeeper) @@ -2283,38 +2944,59 @@ else snprintf(value, sizeof(value), "%s", gGatekeeper); - ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); - ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); - ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); - ast_cli(a->fd, "%-20s%s\n", "Capability:", ast_getformatname_multiple(value, sizeof(value), gCapability)); - ast_cli(a->fd, "%-20s", "DTMF Mode: "); + ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); + + ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); + + ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); + + ast_cli(a->fd, "%-20s%s\n", "Capability:", + ast_getformatname_multiple(value,512,gCapability)); + + ast_cli(a->fd, "%-20s", "DTMF Mode: "); if (gDTMFMode & H323_DTMF_RFC2833) - ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%s\n", "rfc2833"); else if (gDTMFMode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); + ast_cli(a->fd, "%s\n", "q931keypad"); else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); + ast_cli(a->fd, "%s\n", "h245alphanumeric"); else if (gDTMFMode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); + ast_cli(a->fd, "%s\n", "h245signal"); + else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) + ast_cli(a->fd, "%s\n", "inband-relaxed"); + else if (gDTMFMode & H323_DTMF_INBAND) + ast_cli(a->fd, "%s\n", "inband"); else - ast_cli(a->fd, "%s\n", "unknown"); - ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); - ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); + ast_cli(a->fd, "%s\n", "unknown"); + + ast_cli(a->fd,"%-20s", "T.38 Mode: "); + if (gT38Support == T38_DISABLED) + ast_cli(a->fd, "%s\n", "disabled"); + else if (gT38Support == T38_TRANSPARENT) + ast_cli(a->fd, "%s\n", "audio-transparent"); + else if (gT38Support == T38_FAXGW) + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + + ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); + ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); + + ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); pAlias = gAliasList; - if (pAlias) - ast_cli(a->fd, "%-20s\n", "Aliases: "); + if(pAlias) { + ast_cli(a->fd, "%-20s\n", "Aliases: "); + } while (pAlias) { pAliasNext = pAlias->next; if (pAliasNext) { - ast_cli(a->fd, "\t%-30s\t%-30s\n", pAlias->value, pAliasNext->value); + ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value); pAlias = pAliasNext->next; - } else { - ast_cli(a->fd, "\t%-30s\n", pAlias->value); + } + else{ + ast_cli(a->fd,"\t%-30s\n",pAlias->value); pAlias = pAlias->next; } } - return CLI_SUCCESS; } @@ -2325,8 +3007,10 @@ AST_CLI_DEFINE(handle_cli_ooh323_show_peers, "Show defined OOH323 peers"), AST_CLI_DEFINE(handle_cli_ooh323_show_user, "Show details on specific OOH323 user"), AST_CLI_DEFINE(handle_cli_ooh323_show_users, "Show defined OOH323 users"), + AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config") }; + static int load_module(void) { int res; @@ -2337,12 +3021,14 @@ OOH323CALLBACKS h323Callbacks = { .onNewCallCreated = onNewCallCreated, .onAlerting = onAlerting, + .onProgress = onProgress, .onIncomingCall = NULL, - .onOutgoingCall = NULL, + .onOutgoingCall = onOutgoingCall, .onCallEstablished = onCallEstablished, .onCallCleared = onCallCleared, .openLogicalChannels = NULL, - .onReceivedDTMF = &ooh323_onReceivedDigit + .onReceivedDTMF = &ooh323_onReceivedDigit, + .onModeChanged = onModeChanged }; ast_log(LOG_NOTICE, @@ -2379,23 +3065,32 @@ return 0; } ast_rtp_proto_register(&ooh323_rtp); + ast_udptl_proto_register(&ooh323_udptl); ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry)); /* fire up the H.323 Endpoint */ if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) { - ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-OOH323 Disabled\n"); + ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-" + "OOH323 Disabled\n"); return 1; } if (gIsGateway) ooH323EpSetAsGateway(); + ooH323EpSetVersionInfo(t35countrycode, t35extensions, manufacturer, vendor, version); + ooH323EpDisableAutoAnswer(); ooH323EpSetH225MsgCallbacks(h225Callbacks); - ooH323EpSetTraceLevel(OOTRCLVLDBGC); + ooH323EpSetTraceLevel(gTRCLVL); ooH323EpSetLocalAddress(gIP, gPort); ooH323EpSetCallerID(gCallerID); + if(ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart, + ooconfig.mTCPPortEnd) == OO_FAILED) { + ast_log(LOG_ERROR, "h225portrange: Failed to set range\n"); + } + /* Set aliases if any */ for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) { switch (pNewAlias->type) { @@ -2408,20 +3103,18 @@ case T_H225AliasAddress_email_ID: ooH323EpAddAliasEmailID(pNewAlias->value); break; + default: + ; } } ast_mutex_lock(&peerl.lock); peer = peerl.peers; while (peer) { - if (peer->h323id) - ooH323EpAddAliasH323ID(peer->h323id); - if (peer->email) - ooH323EpAddAliasEmailID(peer->email); - if (peer->e164) - ooH323EpAddAliasDialedDigits(peer->e164); - if (peer->url) - ooH323EpAddAliasURLID(peer->url); + if(peer->h323id) ooH323EpAddAliasH323ID(peer->h323id); + if(peer->email) ooH323EpAddAliasEmailID(peer->email); + if(peer->e164) ooH323EpAddAliasDialedDigits(peer->e164); + if(peer->url) ooH323EpAddAliasURLID(peer->url); peer = peer->next; } ast_mutex_unlock(&peerl.lock); @@ -2441,6 +3134,11 @@ if (!gTunneling) ooH323EpDisableH245Tunneling(); + if (gBeMaster) + ooH323EpTryBeMaster(1); + + ooH323EpEnableManualRingback(); + /* Gatekeeper */ if (gRasGkMode == RasUseSpecificGatekeeper) ooGkClientInit(gRasGkMode, gGatekeeper, 0); @@ -2456,17 +3154,18 @@ return 1; } - /* Create H.323 listener */ if (ooCreateH323Listener() != OO_OK) { - ast_log(LOG_ERROR, "OOH323 Listener Creation failure. OOH323 DISABLED\n"); + ast_log(LOG_ERROR, "OOH323 Listener Creation failure. " + "OOH323 DISABLED\n"); ooH323EpDestroy(); return 1; } if (ooh323c_start_stack_thread() < 0) { - ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. OOH323 DISABLED\n"); + ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. " + "OOH323 DISABLED\n"); ooH323EpDestroy(); return 1; } @@ -2496,6 +3195,7 @@ ast_verb(1, "Reloading H.323\n"); ooh323_do_reload(); } + /* Check for interfaces needing to be killed */ ast_mutex_lock(&iflock); time(&t); @@ -2506,11 +3206,21 @@ /* TODO: Need to add rtptimeout keepalive support */ if (ast_test_flag(h323, H323_NEEDDESTROY)) { ooh323_destroy (h323); - } + } /* else if (ast_test_flag(h323, H323_NEEDSTART) && h323->owner) { + ast_channel_lock(h323->owner); + if (ast_pbx_start(h323->owner)) { + ast_log(LOG_WARNING, "Unable to start PBX on %s\n", h323->owner->name); + ast_channel_unlock(h323->owner); + ast_hangup(h323->owner); + } + ast_channel_unlock(h323->owner); + ast_clear_flag(h323, H323_NEEDSTART); + } */ h323 = h323_next; } ast_mutex_unlock(&iflock); pthread_testcancel(); + /* Wait for sched or io */ res = ast_sched_wait(sched); if ((res < 0) || (res > 1000)) { @@ -2567,7 +3277,7 @@ { /* NOTE: Assumes iflock already acquired */ struct ooh323_pvt *prev = NULL, *cur = NULL; - + struct ooh323_user *user = NULL; if (gH323Debug) { ast_verbose("--- ooh323_destroy \n"); @@ -2591,6 +3301,7 @@ iflist = cur->next; if (cur->callToken) { + if (gH323Debug) ast_verbose(" Destroying %s\n", cur->callToken); free(cur->callToken); cur->callToken = 0; } @@ -2620,10 +3331,20 @@ ast_rtp_destroy(cur->rtp); cur->rtp = 0; } + + if (cur->udptl) { + ast_udptl_destroy(cur->udptl); + cur->udptl = NULL; + } /* Unlink us from the owner if we have one */ if (cur->owner) { - ast_channel_lock(cur->owner); + while(ast_channel_trylock(cur->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&cur->lock); + usleep(1); + ast_mutex_lock(&cur->lock); + } ast_debug(1, "Detaching from %s\n", cur->owner->name); cur->owner->tech_pvt = NULL; ast_channel_unlock(cur->owner); @@ -2634,6 +3355,23 @@ ast_dsp_free(cur->vad); cur->vad = NULL; } + +/* decrement user/peer count */ + + if(!ast_test_flag(cur, H323_OUTGOING)) { + if (cur->neighbor.user) { + user = find_user(p->callerid_name, cur->neighbor.user); + if(user && user->inUse > 0) { + ast_mutex_lock(&user->lock); + user->inUse--; + ast_mutex_unlock(&user->lock); + } + free(cur->neighbor.user); + } + } else { +/* outgoing limit decrement here !!! */ + } + ast_mutex_unlock(&cur->lock); ast_mutex_destroy(&cur->lock); @@ -2656,14 +3394,10 @@ cur = cur->next; ast_mutex_destroy(&prev->lock); - if (prev->h323id) - free(prev->h323id); - if (prev->email) - free(prev->email); - if (prev->url) - free(prev->url); - if (prev->e164) - free(prev->e164); + if(prev->h323id) free(prev->h323id); + if(prev->email) free(prev->email); + if(prev->url) free(prev->url); + if(prev->e164) free(prev->e164); free(prev); if (cur == peerl.peers) { @@ -2705,8 +3439,8 @@ /* First, take us out of the channel loop */ ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry)); ast_rtp_proto_unregister(&ooh323_rtp); + ast_udptl_proto_unregister(&ooh323_udptl); ast_channel_unregister(&ooh323_tech); - #if 0 ast_unregister_atexit(&ast_ooh323c_exit); #endif @@ -2880,15 +3614,25 @@ return OO_G711ALAW64K; case AST_FORMAT_GSM: return OO_GSMFULLRATE; + +#ifdef AST_FORMAT_AMRNB + case AST_FORMAT_AMRNB: + return OO_AMRNB; +#endif + case AST_FORMAT_G729A: return OO_G729A; + case AST_FORMAT_G726: + return OO_G726; + case AST_FORMAT_G726_AAL2: + return OO_G726AAL2; case AST_FORMAT_G723_1: return OO_G7231; case AST_FORMAT_H263: return OO_H263VIDEO; default: ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", - ast_getformatname_multiple(formats, sizeof(formats), cap)); + ast_getformatname_multiple(formats,512,cap)); return -1; } } @@ -2954,9 +3698,25 @@ ooAddMediaInfo(call, mediaInfo); strcpy(mediaInfo.dir, "receive"); ooAddMediaInfo(call, mediaInfo); + + strcpy(mediaInfo.dir, "transmit"); + mediaInfo.cap = OO_G729B; + ooAddMediaInfo(call, mediaInfo); + strcpy(mediaInfo.dir, "receive"); + ooAddMediaInfo(call, mediaInfo); } } + ast_udptl_get_us(p->udptl, &us); + ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP)); + mediaInfo.lMediaPort = ntohs(us.sin_port); + mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1; + mediaInfo.cap = OO_T38; + strcpy(mediaInfo.dir, "transmit"); + ooAddMediaInfo(call, mediaInfo); + strcpy(mediaInfo.dir, "receive"); + ooAddMediaInfo(call, mediaInfo); + if (gH323Debug) ast_verbose("+++ configure_local_rtp\n"); @@ -2985,9 +3745,11 @@ them.sin_port = htons(remotePort); ast_rtp_set_peer(p->rtp, &them); - if (gH323Debug) { + if (p->writeformat & AST_FORMAT_G726_AAL2) + ast_rtp_set_rtpmap_type(p->rtp, 2, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD); + + if(gH323Debug) ast_verbose("+++ setup_rtp_connection\n"); - } return; } @@ -2996,13 +3758,13 @@ { struct ooh323_pvt *p = NULL; - if (gH323Debug) { + if(gH323Debug) ast_verbose("--- close_rtp_connection\n"); - } p = find_call(call); if (!p) { - ast_log(LOG_ERROR, "Couldn't find matching call to close rtp connection\n"); + ast_log(LOG_ERROR, "Couldn't find matching call to close rtp " + "connection\n"); return; } ast_mutex_lock(&p->lock); @@ -3011,13 +3773,156 @@ } ast_mutex_unlock(&p->lock); - if (gH323Debug) { + if(gH323Debug) ast_verbose("+++ close_rtp_connection\n"); + + return; +} + +/* + udptl handling functions + */ + +static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan) +{ + struct ooh323_pvt *p; + struct ast_udptl *udptl = NULL; + + p = chan->tech_pvt; + if (!p) + return NULL; + + ast_mutex_lock(&p->lock); + if (p->udptl) + udptl = p->udptl; + ast_mutex_unlock(&p->lock); + return udptl; +} + +static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) +{ + struct ooh323_pvt *p; + + p = chan->tech_pvt; + if (!p) + return -1; + ast_mutex_lock(&p->lock); + if (udptl) + ast_udptl_get_peer(udptl, &p->udptlredirip); + else + memset(&p->udptlredirip, 0, sizeof(p->udptlredirip)); + + ast_mutex_unlock(&p->lock); + return 0; +} + +void setup_udptl_connection(ooCallData *call, const char *remoteIp, + int remotePort) +{ + struct ooh323_pvt *p = NULL; + struct sockaddr_in them; + + if (gH323Debug) + ast_verbose("--- setup_udptl_connection\n"); + + /* Find the call or allocate a private structure if call not found */ + p = find_call(call); + + if (!p) { + ast_log(LOG_ERROR, "Something is wrong: rtp\n"); + return; } + ast_mutex_lock(&p->lock); + if (p->owner) { + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + } else { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + + them.sin_family = AF_INET; + them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */ + them.sin_port = htons(remotePort); + ast_udptl_set_peer(p->udptl, &them); + p->t38_tx_enable = 1; + p->lastTxT38 = time(NULL); + if (p->t38support == T38_FAXGW) { + enum ast_control_t38 message = AST_T38_NEGOTIATED; + ast_queue_control_data(p->owner, AST_CONTROL_T38, &message, sizeof(message)); + } + if (gH323Debug) + ast_debug(1, "Receiving UDPTL %s:%d\n", ast_inet_ntoa(them.sin_addr), + ntohs(them.sin_port)); + + ast_channel_unlock(p->owner); + ast_mutex_unlock(&p->lock); + + if(gH323Debug) + ast_verbose("+++ setup_udptl_connection\n"); + + return; +} + +void close_udptl_connection(ooCallData *call) +{ + struct ooh323_pvt *p = NULL; + + if(gH323Debug) + ast_verbose("--- close_udptl_connection\n"); + + p = find_call(call); + if (!p) { + ast_log(LOG_ERROR, "Couldn't find matching call to close udptl " + "connection\n"); + return; + } + ast_mutex_lock(&p->lock); + if (p->owner) { + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + } else { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + + p->t38_tx_enable = 0; + if (p->t38support == T38_FAXGW) { + enum ast_control_t38 message = AST_T38_TERMINATED; + ast_queue_control_data(p->owner, AST_CONTROL_T38, &message, sizeof(message)); + } + + ast_channel_unlock(p->owner); + ast_mutex_unlock(&p->lock); + + if(gH323Debug) + ast_verbose("+++ close_udptl_connection\n"); + return; } +/* end of udptl handling */ int update_our_aliases(ooCallData *call, struct ooh323_pvt *p) { @@ -3032,7 +3937,8 @@ updated = 1; } if (psAlias->type == T_H225AliasAddress_dialedDigits) { - ast_copy_string(p->callee_dialedDigits, psAlias->value, sizeof(p->callee_dialedDigits)); + ast_copy_string(p->callee_dialedDigits, psAlias->value, + sizeof(p->callee_dialedDigits)); updated = 1; } if (psAlias->type == T_H225AliasAddress_url_ID) { @@ -3065,33 +3971,252 @@ case 3: f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */ break; + case 5: + f = ast_udptl_read(p->udptl); /* UDPTL t.38 data */ + if (gH323Debug) ast_debug(1, "Got UDPTL %d/%d len %d for %s\n", + f->frametype, f->subclass, f->datalen, ast->name); + +/* if not transparent audio t.38 mode */ + if (p->t38support != T38_TRANSPARENT) + break; + + if (!p->faxmode) p->faxmode = 1; + if (p->t38_init) { + t38_core_rx_ifp_packet(&p->t38r_state.t38x.t38, (uint8_t *)f->data.ptr, + f->datalen, 0); + p->lastTxT38 = time(NULL); + } + f = &null_frame; + break; + default: f = &null_frame; } + /* Don't send RFC2833 if we're not supposed to */ - if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) { - return &null_frame; - } + /* if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) { + return &null_frame; */ + if (p->owner) { /* We already hold the channel lock */ - if (f->frametype == AST_FRAME_VOICE) { + if (f->frametype == AST_FRAME_VOICE && !p->faxmode) { if (f->subclass != p->owner->nativeformats) { - ast_debug(1, "Oooh, format changed to %d\n", f->subclass); + ast_debug(1, "Oooh, format changed to %d\n", f->subclass); p->owner->nativeformats = f->subclass; ast_set_read_format(p->owner, p->owner->readformat); ast_set_write_format(p->owner, p->owner->writeformat); } - if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad) { + /* if (!p->owner->readformat) + p->owner->readformat = p->owner->nativeformats; */ + + if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad && + (f->subclass == AST_FORMAT_SLINEAR || f->subclass == AST_FORMAT_ALAW || + f->subclass == AST_FORMAT_ULAW)) { f = ast_dsp_process(p->owner, p->vad, f); - if (f && (f->frametype == AST_FRAME_DTMF)) { - ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); - } + if (f && (f->frametype == AST_FRAME_DTMF)) + ast_debug(1, "* Detected inband DTMF '%c'\n",f->subclass); } } } return f; } +static int t30_read(const void *data) { + + struct ast_channel *c = (struct ast_channel *) data; + struct ooh323_pvt *p = (struct ooh323_pvt *) c->tech_pvt; + int len; + + static uint8_t buffer[AST_FRIENDLY_OFFSET + MAXT30 * sizeof(uint16_t)]; + int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET); + static struct ast_frame outf = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_SLINEAR, + }; + + + if (!p) { + ast_log(LOG_ERROR, "No private structure for %s\n", c->name); + return 0; + } + + ast_mutex_lock(&p->lock); + + if (p->owner) { + while (p->owner && ast_channel_trylock(c)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + } else { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return 0; + } + + + + if (p->faxmode && p->t38_init && p->t38_tx_enable) { + + + if ((len = t38_gateway_tx(&p->t38r_state, buf, MAXT30))) { + + outf.samples = len; + AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, + len * sizeof(int16_t)); + ast_queue_frame(c, &outf); + + } + } + + ast_channel_unlock(c); + ast_mutex_unlock(&p->lock); + return 0; +} + + +static int t38_tx_packet_handler(t38_core_state_t *s, void *data, + unsigned int* buf, int len, int cout) +{ + struct ast_frame f = { AST_FRAME_MODEM, AST_MODEM_T38 }; + struct ooh323_pvt* p = (struct ooh323_pvt*) data; + int res; + f.datalen = len; + f.data.ptr = buf; + f.offset = 0; + + if (gH323Debug) + ast_debug(1, "Sending UDPTL packet of %d bytes\n", len); + if (p) { + ast_mutex_lock(&p->lock); + if (p->udptl) { + res = ast_udptl_write(p->udptl, &f); + p->lastTxT38 = time(NULL); + } + ast_mutex_unlock(&p->lock); + } + return 0; + +} + +static void span_message(int level, const char* msg) { + if (gH323Debug) ast_debug(1, msg); +} + + +void onModeChanged(ooCallData *call, int t38mode) { + struct ooh323_pvt *p; + struct ast_frame f; + + p = find_call(call); + if (!p) { + ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken); + return; + } + + ast_mutex_lock(&p->lock); + + if (gH323Debug) + ast_debug(1, "change mode to %d for %s\n", t38mode, call->callToken); + + if (t38mode == p->faxmode) { + if (gH323Debug) + ast_debug(1, "mode for %s is already %d\n", call->callToken, + t38mode); + ast_mutex_unlock(&p->lock); + return; + } + + if (p->owner) { + while (p->owner && ast_channel_trylock(p->owner)) { + ast_debug(1,"Failed to grab lock, trying again\n"); + ast_mutex_unlock(&p->lock); + usleep(1); + ast_mutex_lock(&p->lock); + } + if (!p->owner) { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + } else { + ast_mutex_unlock(&p->lock); + ast_log(LOG_ERROR, "Channel has no owner\n"); + return; + } + + if (t38mode) { + + + if (p->t38support == T38_FAXGW) { +/* AST_T38_CONTROL mode */ + + enum ast_control_t38 message = AST_T38_REQUEST_NEGOTIATE; + ast_queue_control_data(p->owner, AST_CONTROL_T38, &message, sizeof(message)); + p->faxmode = 1; + + } else if (t38_gateway_init(&p->t38r_state, t38_tx_packet_handler, p)) { +/* transparent slinear mode */ + + p->t38_init = 1; + + t38_gateway_set_transmit_on_idle(&p->t38r_state, FALSE); + + span_log_set_tag(&p->t38r_state.logging, "T.38G"); + span_log_set_tag(&p->t38r_state.t38x.t38.logging, "T.38"); + + span_log_set_message_handler(&p->t38r_state.logging, span_message); + span_log_set_message_handler(&p->t38r_state.t38x.t38.logging, span_message); + + span_log_set_level(&p->t38r_state.logging, + SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_level(&p->t38r_state.t38x.t38.logging, + SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + + + t38_set_t38_version(&p->t38r_state.t38x.t38, 0); + + t38_set_sequence_number_handling(&p->t38r_state.t38x.t38,0); + + t38_gateway_set_ecm_capability(&p->t38r_state, 1); + + t38_gateway_set_tep_mode(&p->t38r_state, TRUE); + + t38_gateway_set_supported_modems(&p->t38r_state, + T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER); + + if (gH323Debug) + ast_debug(1,"Going to change native format for %s\n", call->callToken); + p->owner->nativeformats = AST_FORMAT_SLINEAR; + p->owner->rawreadformat = AST_FORMAT_SLINEAR; + p->owner->rawwriteformat = AST_FORMAT_SLINEAR; + ast_set_read_format(p->owner, p->owner->rawreadformat); + ast_set_write_format(p->owner, p->owner->rawwriteformat); + p->faxmode = 1; + ast_settimeout(p->owner, 34, t30_read, p->owner); + p->lastTxT38 = time(NULL); + } + } else { + if (p->t38support == T38_FAXGW) { + enum ast_control_t38 message = AST_T38_REQUEST_TERMINATE; + ast_queue_control_data(p->owner, AST_CONTROL_T38, &message, sizeof(message)); + } + p->faxmode = 0; + p->t38_init = 0; + } + + p->chmodepend = 0; + ast_channel_unlock(p->owner); + ast_mutex_unlock(&p->lock); +} + + int ooh323_convert_hangupcause_asteriskToH323(int cause) { @@ -3116,6 +4241,8 @@ } return 0; + + } int ooh323_convert_hangupcause_h323ToAsterisk(int cause) --- ./channels/ooh323cDriver.c 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323cDriver.c 2009-07-28 22:49:05.000000000 +0400 @@ -18,11 +18,15 @@ #include #include -#include + +#undef AST_BACKGROUND_STACKSIZE +#define AST_BACKGROUND_STACKSIZE 768 * 1024 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; @@ -32,6 +36,11 @@ 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) { @@ -39,13 +48,70 @@ return dummy; } +void* ooh323c_cmd_thread(void* dummy) +{ + + ooMonitorCmdChannels(); + return dummy; +} + +void* ooh323c_call_thread(void* dummy) +{ + ooMonitorCallChannels((ooCallData*)dummy); + /* ast_mutex_lock(&call->Lock); + ast_mutex_unlock(&call->Lock); + ast_mutex_destroy(&call->Lock); + memFreePtr(&gH323ep.ctxt, call); */ + return dummy; +} + +/* int ooh323c_start_call_thread(ooCallData *call) { + if(ast_pthread_create(&call->callThread, NULL, ooh323c_call_thread, call) < 0) + { + ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", call->callToken); + return -1; + } + return 0; +} */ + +int ooh323c_start_call_thread(ooCallData *call) { + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if(ast_pthread_create_background(&call->callThread, &attr, ooh323c_call_thread, call) < 0) + { + ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", call->callToken); + pthread_attr_destroy(&attr); + return -1; + } + pthread_attr_destroy(&attr); + return 0; +} + + +int ooh323c_stop_call_thread(ooCallData *call) { + if (call->callThread != AST_PTHREADT_NULL) { + ooStopMonitorCallChannels(call); + /* pthread_join(call->callThread, NULL); + call->callThread = AST_PTHREADT_NULL;*/ + } + 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,6 +122,8 @@ ooStopMonitor(); pthread_join(ooh323c_thread, NULL); ooh323c_thread = AST_PTHREADT_NULL; + pthread_join(ooh323cmd_thread, NULL); + ooh323cmd_thread = AST_PTHREADT_NULL; } return 0; } @@ -107,6 +175,13 @@ &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) @@ -121,6 +196,30 @@ } + 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, + &ooh323c_stop_transmit_channel); + + } + if(format & AST_FORMAT_H263) { if(gH323Debug) @@ -145,6 +244,20 @@ } +#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 + } if(dtmf & H323_DTMF_RFC2833) @@ -158,20 +271,27 @@ } 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 t38support) { int ret, 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) + if(dtmf & H323_DTMF_RFC2833 || 1) ret |= ooCallEnableDTMFRFC2833(call,0); - else if(dtmf & H323_DTMF_H245ALPHANUMERIC) + 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++) { @@ -202,26 +322,63 @@ &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, 4, + 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, 4, 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, 4, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); + } if(format & AST_FORMAT_G723_1) @@ -261,6 +418,20 @@ &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 } } @@ -295,9 +466,9 @@ { 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 +480,9 @@ { int fmt=-1; fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap); - if(fmt>0) + if(fmt>0) { ooh323_set_write_format(call, fmt); - else{ + }else{ ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n", call->callToken); return -1; @@ -331,6 +502,29 @@ 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 +536,24 @@ return AST_FORMAT_ALAW; case OO_GSMFULLRATE: return AST_FORMAT_GSM; + +#ifdef AST_FORMAT_AMRNB + case OO_AMRNB: + return AST_FORMAT_AMRNB; +#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: --- ./channels/ooh323c/src/ooq931.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooq931.h 2009-05-30 06:40:48.000000000 +0400 @@ -45,7 +45,7 @@ #define OO_MAX_NUMBER_LENGTH 50 /* Maximum value for a call token identifier */ -#define OO_MAX_CALL_TOKEN 9999 +#define OO_MAX_CALL_TOKEN 999999 /* Q.931 packet must be at least 5 bytes long */ #define Q931_E_TOOSHORT (-1001) @@ -346,7 +346,7 @@ * * @return OO_OK, on success. OO_FAILED, on failure. */ -EXTERN int ooDecodeUUIE(Q931Message *q931Msg); +EXTERN int ooDecodeUUIE(OOCTXT* pctxt, Q931Message *q931Msg); /** * This function is used to encode the UUIE field of the Q931 message. @@ -356,7 +356,7 @@ * * @return OO_OK, on success. OO_FAILED, on failure. */ -EXTERN int ooEncodeUUIE(Q931Message *q931msg); +EXTERN int ooEncodeUUIE(OOCTXT* pctxt, Q931Message *q931msg); /** * This function is invoked to retrieve an IE element from a Q931 message. @@ -388,7 +388,7 @@ * * @return Completion status - 0 on success, -1 on failure */ -EXTERN int ooCreateQ931Message(Q931Message **msg, int msgType); +EXTERN int ooCreateQ931Message(OOCTXT* pctxt, Q931Message **msg, int msgType); /** * This function is invoked to generate a unique call reference number. @@ -414,7 +414,7 @@ * * @return Completion status - 0 on success, -1 on failure */ -EXTERN int ooFreeQ931Message(Q931Message *q931Msg); +EXTERN int ooFreeQ931Message(OOCTXT* pctxt, Q931Message *q931Msg); /** * This function is invoked to retrive the outgoing message buffer for @@ -549,7 +549,7 @@ * * @return OO_OK, on success. OO_FAILED, on failure. */ -EXTERN int ooH323HangCall(char * callToken, OOCallClearReason reason); +EXTERN int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931); /** @@ -648,7 +648,7 @@ * * @return OO_OK on success, OO_FAILED, on failure. */ -EXTERN int ooQ931SetKeypadIE(Q931Message *pmsg, const char* data); +EXTERN int ooQ931SetKeypadIE(OOCTXT* pctxt, Q931Message *pmsg, const char* data); /** * This function is used to add a bearer capability IE to a Q931 message. @@ -663,7 +663,7 @@ * @return OO_OK on success, OO_FAILED, on failure. */ EXTERN int ooSetBearerCapabilityIE - (Q931Message *pmsg, enum Q931CodingStandard codingStandard, + (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CodingStandard codingStandard, enum Q931InformationTransferCapability capability, enum Q931TransferMode transferMode, enum Q931TransferRate transferRate, enum Q931UserInfoLayer1Protocol userInfoLayer1); @@ -679,7 +679,7 @@ * @return OO_OK, on success. OO_FAILED, on failure. */ EXTERN int ooQ931SetCalledPartyNumberIE - (Q931Message *pmsg, const char *number, unsigned plan, unsigned type); + (OOCTXT *pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type); /** @@ -696,7 +696,7 @@ * @return OO_OK, on success. OO_FAILED, on failure. */ EXTERN int ooQ931SetCallingPartyNumberIE - (Q931Message *pmsg, const char *number, unsigned plan, unsigned type, + (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type, unsigned presentation, unsigned screening); /** @@ -709,7 +709,7 @@ * @return OO_OK, on success. OO_FAILED, on failure. */ EXTERN int ooQ931SetCauseIE - (Q931Message *pmsg,enum Q931CauseValues cause, unsigned coding, + (OOCTXT *pctxt, Q931Message *pmsg,enum Q931CauseValues cause, unsigned coding, unsigned location); /** --- ./channels/ooh323c/src/oochannels.c 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/oochannels.c 2009-07-03 23:58:03.000000000 +0400 @@ -13,6 +13,8 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include #include "ooports.h" #include "oochannels.h" @@ -30,8 +32,11 @@ #include "ooCmdChannel.h" #include "ootypes.h" + /** Global endpoint structure */ extern OOH323EndPoint gH323ep; +extern ast_mutex_t callListLock; +extern ast_mutex_t monitorLock; extern DList g_TimerList; @@ -60,7 +65,7 @@ *(call->h245listenport) = ret; call->h245listener = (OOSOCKET*)memAlloc(call->pctxt, sizeof(OOSOCKET)); *(call->h245listener) = channelSocket; - ret = ooSocketListen(*(call->h245listener), 20); + ret = ooSocketListen(*(call->h245listener), 4096); if(ret != ASN_OK) { OOTRACEERR3("Error:Unable to listen on H.245 socket (%s, %s)\n", @@ -228,8 +233,9 @@ int ooCreateH225Connection(OOH323CallData *call) { - int ret=0; + int ret=0, i; OOSOCKET channelSocket=0; + for (i=0;i<3;i++) { if((ret=ooSocketCreate (&channelSocket))!=ASN_OK) { OOTRACEERR3("Failed to create socket for transmit H2250 channel (%s, %s)" @@ -314,19 +320,22 @@ } else { - OOTRACEERR3("ERROR:Failed to connect to remote destination for " - "transmit H2250 channel(%s, %s)\n",call->callType, - call->callToken); + OOTRACEERR5("ERROR:Failed to connect to remote destination for " + "transmit H2250 channel(%s, %s, %d, %s)\n",call->callType, + call->callToken, channelSocket, call->localIP); + close(channelSocket); + if(call->callState < OO_CALL_CLEAR) { /* No one is listening at remote end */ call->callState = OO_CALL_CLEAR; call->callEndReason = OO_REASON_NOUSER; } - return OO_FAILED; + if (i>=2) return OO_FAILED; else continue; } return OO_FAILED; - } + } + } } int ooCloseH225Connection (OOH323CallData *call) @@ -364,7 +373,7 @@ gH323ep.listener = (OOSOCKET*)memAlloc(&gH323ep.ctxt,sizeof(OOSOCKET)); *(gH323ep.listener) = channelSocket; - ooSocketListen(channelSocket,20); /*listen on socket*/ + ooSocketListen(channelSocket,2048); /*listen on socket*/ OOTRACEINFO1("H323 listener creation - successful\n"); return OO_OK; } @@ -399,6 +408,7 @@ return OO_FAILED; } + ast_mutex_lock(&call->Lock); call->pH225Channel = (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel)); @@ -422,13 +432,15 @@ call->callState = OO_CALL_CLEAR; call->callEndReason = OO_REASON_TRANSPORTFAILURE; } + ast_mutex_unlock(&call->Lock); return OO_FAILED; } OOTRACEDBGA4("Using Local IP address %s for incoming call in multihomed " "mode. (%s, %s)\n", call->localIP, call->callType, call->callToken); } - + + ast_mutex_unlock(&call->Lock); return OO_OK; } @@ -475,81 +487,108 @@ } -int ooSetFDSETs(fd_set *pReadfds, fd_set *pWritefds, int *nfds) +int ooSetCmdFDSETs(struct pollfd *pfds, int *nfds) { OOH323CallData *call=NULL; + if(gH323ep.cmdSock) + { + pfds[*nfds].fd = gH323ep.cmdSock; + pfds[*nfds].events = POLLIN; + (*nfds)++; + } + + return OO_OK; + +} + +int ooProcessCmdFDSETsAndTimers + (struct pollfd *pfds, int nfds, struct timeval *pToMin) +{ + OOH323CallData *call, *prev=NULL; + struct timeval toNext; + + if(gH323ep.cmdSock) { + if(ooPDRead(pfds, nfds, gH323ep.cmdSock)) { + if(ooReadAndProcessStackCommand() != OO_OK) { + /* ooReadAndProcessStackCommand prints an error message */ + return OO_FAILED; + } + } + } + + return OO_OK; + +} + + +int ooSetFDSETs(struct pollfd *pfds, int *nfds) +{ if(gH323ep.gkClient && gH323ep.gkClient->rasSocket != 0) { - FD_SET(gH323ep.gkClient->rasSocket, pReadfds ); - if ( *nfds < (int)gH323ep.gkClient->rasSocket) - *nfds = (int)gH323ep.gkClient->rasSocket; + pfds[*nfds].fd = gH323ep.gkClient->rasSocket; + pfds[*nfds].events = POLLIN; + (*nfds)++; } if(gH323ep.listener) { - FD_SET(*(gH323ep.listener), pReadfds); - if(*nfds < (int)*(gH323ep.listener)) - *nfds = *((int*)gH323ep.listener); + pfds[*nfds].fd = *gH323ep.listener; + pfds[*nfds].events = POLLIN; + (*nfds)++; } - if(gH323ep.cmdSock) - { - FD_SET(gH323ep.cmdSock, pReadfds); - if(*nfds < (int)gH323ep.cmdSock) - *nfds = (int)gH323ep.cmdSock; - } + return OO_OK; +} - - if(gH323ep.callList) - { - call = gH323ep.callList; - while(call) - { - if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) - { - FD_SET (call->pH225Channel->sock, pReadfds); - if (call->pH225Channel->outQueue.count > 0 || - (OO_TESTFLAG (call->flags, OO_M_TUNNELING) && - 0 != call->pH245Channel && - call->pH245Channel->outQueue.count>0)) - FD_SET (call->pH225Channel->sock, pWritefds); - if(*nfds < (int)call->pH225Channel->sock) - *nfds = call->pH225Channel->sock; - } +int ooSetCallFDSETs(OOH323CallData* call, struct pollfd* pfds, int *nfds) +{ + + if(call) { + + if(call->cmdSock && call->callState < OO_CALL_CLEAR) { + pfds[*nfds].fd = call->cmdSock; + pfds[*nfds].events = POLLIN; + (*nfds)++; + } + + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) { + pfds[*nfds].fd = call->pH225Channel->sock; + pfds[*nfds].events = POLLIN; + + if (call->pH225Channel->outQueue.count > 0 || + (OO_TESTFLAG (call->flags, OO_M_TUNNELING) && + 0 != call->pH245Channel && + call->pH245Channel->outQueue.count>0)) + pfds[*nfds].events |= POLLOUT; + (*nfds)++; + + } - if (0 != call->pH245Channel && call->pH245Channel->sock != 0) - { - FD_SET(call->pH245Channel->sock, pReadfds); - if (call->pH245Channel->outQueue.count>0) - FD_SET(call->pH245Channel->sock, pWritefds); - if(*nfds < (int)call->pH245Channel->sock) - *nfds = call->pH245Channel->sock; - } - else if(call->h245listener) - { - OOTRACEINFO3("H.245 Listerner socket being monitored " - "(%s, %s)\n", call->callType, call->callToken); - FD_SET(*(call->h245listener), pReadfds); - if(*nfds < (int)*(call->h245listener)) - *nfds = *(call->h245listener); - } - call = call->next; - - }/* while(call) */ - }/*if(gH323ep.callList) */ + if (0 != call->pH245Channel && call->pH245Channel->sock != 0) { + pfds[*nfds].fd = call->pH245Channel->sock; + pfds[*nfds].events = POLLIN; + if (call->pH245Channel->outQueue.count>0) + pfds[*nfds].events |= POLLOUT; + (*nfds)++; + } + else if(call->h245listener) { + OOTRACEINFO3("H.245 Listerner socket being monitored " + "(%s, %s)\n", call->callType, call->callToken); + pfds[*nfds].fd = *(call->h245listener); + pfds[*nfds].events = POLLIN; + (*nfds)++; + } - if(*nfds != 0) *nfds = *nfds+1; + } return OO_OK; - } - + int ooProcessFDSETsAndTimers - (fd_set *pReadfds, fd_set *pWritefds, struct timeval *pToMin) + (struct pollfd* pfds, int nfds, struct timeval *pToMin) { - OOH323CallData *call, *prev=NULL; struct timeval toNext; /* Process gatekeeper client timers */ @@ -576,20 +615,11 @@ } } - if(gH323ep.cmdSock) { - if(FD_ISSET(gH323ep.cmdSock, pReadfds)) { - if(ooReadAndProcessStackCommand() != OO_OK) { - /* ooReadAndProcessStackCommand prints an error message */ - return OO_FAILED; - } - } - } - /* Manage ready descriptors after select */ if(0 != gH323ep.gkClient && 0 != gH323ep.gkClient->rasSocket) { - if(FD_ISSET( gH323ep.gkClient->rasSocket, pReadfds) ) + if(ooPDRead(pfds, nfds, gH323ep.gkClient->rasSocket) ) { ooGkClientReceive(gH323ep.gkClient); if(gH323ep.gkClient->state == GkClientFailed || @@ -601,7 +631,7 @@ if(gH323ep.listener) { - if(FD_ISSET(*(gH323ep.listener), pReadfds)) + if(ooPDRead(pfds, nfds, *(gH323ep.listener))) { OOTRACEDBGA1("New connection at H225 receiver\n"); ooAcceptH225Connection(); @@ -609,102 +639,180 @@ } - if(gH323ep.callList) - { - call = gH323ep.callList; - while(call) - { - ooTimerFireExpired(call->pctxt, &call->timerList); - if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) - { - if(FD_ISSET(call->pH225Channel->sock, pReadfds)) - { - if(ooH2250Receive(call) != OO_OK) - { - OOTRACEERR3("ERROR:Failed ooH2250Receive - Clearing call " - "(%s, %s)\n", call->callType, call->callToken); - if(call->callState < OO_CALL_CLEAR) - { - call->callEndReason = OO_REASON_INVALIDMESSAGE; - call->callState = OO_CALL_CLEAR; - } - } - } - } + return OO_OK; +} +int ooProcessCallFDSETsAndTimers + (OOH323CallData *call, struct pollfd* pfds, int nfds, struct timeval *pToMin) +{ + struct timeval toNext; - if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) - { - if(FD_ISSET(call->pH245Channel->sock, pReadfds)) - { - ooH245Receive(call); - } - } - - if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) - { - if(FD_ISSET(call->pH245Channel->sock, pWritefds)) - { - if(call->pH245Channel->outQueue.count>0) - ooSendMsg(call, OOH245MSG); - } - } - else if(call->h245listener) - { - if(FD_ISSET(*(call->h245listener), pReadfds)) - { - OOTRACEDBGC3("Incoming H.245 connection (%s, %s)\n", - call->callType, call->callToken); - ooAcceptH245Connection(call); - } - } + if(call) + { - if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) - { - if(FD_ISSET(call->pH225Channel->sock, pWritefds)) - { - if(call->pH225Channel->outQueue.count>0) - { - OOTRACEDBGC3("Sending H225 message (%s, %s)\n", - call->callType, call->callToken); - ooSendMsg(call, OOQ931MSG); - } - if(call->pH245Channel && - call->pH245Channel->outQueue.count>0 && - OO_TESTFLAG (call->flags, OO_M_TUNNELING)) - { - OOTRACEDBGC3("H245 message needs to be tunneled. " - "(%s, %s)\n", call->callType, + if(call->cmdSock) { + if(ooPDRead(pfds, nfds, call->cmdSock)) { + ast_mutex_lock(&call->Lock); + if(ooReadAndProcessCallStackCommand(call) != OO_OK) { + /* ooReadAndProcessStackCommand prints an error message */ + ast_mutex_unlock(&call->Lock); + return OO_FAILED; + } + ast_mutex_unlock(&call->Lock); + } + } + + ooTimerFireExpired(call->pctxt, &call->timerList); + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) + { + if(ooPDRead(pfds, nfds, call->pH225Channel->sock)) + { + if(ooH2250Receive(call) != OO_OK) + { + OOTRACEERR3("ERROR:Failed ooH2250Receive - Clearing call " + "(%s, %s)\n", call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + } + } + } + + if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) + if(ooPDRead(pfds, nfds, call->pH245Channel->sock)) + ooH245Receive(call); + + if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) + { + if(call->pH245Channel->outQueue.count>0) + { + if(ooPDWrite(pfds, nfds, call->pH245Channel->sock)) + ooSendMsg(call, OOH245MSG); + } + } + else if(call->h245listener) + { + if(ooPDRead(pfds, nfds, *(call->h245listener))) + { + OOTRACEDBGC3("Incoming H.245 connection (%s, %s)\n", + call->callType, call->callToken); + ooAcceptH245Connection(call); + } + } + + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) + { + if(ooPDWrite(pfds, nfds, call->pH225Channel->sock)) + { + if(call->pH225Channel->outQueue.count>0) + { + OOTRACEDBGC3("Sending H225 message (%s, %s)\n", + call->callType, call->callToken); + ooSendMsg(call, OOQ931MSG); + } + if(call->pH245Channel && + call->pH245Channel->outQueue.count>0 && + OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + { + OOTRACEDBGC3("H245 message needs to be tunneled. " + "(%s, %s)\n", call->callType, call->callToken); - ooSendMsg(call, OOH245MSG); - } - } - } + ooSendMsg(call, OOH245MSG); + } + } + } - if(ooTimerNextTimeout(&call->timerList, &toNext)) - { - if(ooCompareTimeouts(pToMin, &toNext) > 0) - { - pToMin->tv_sec = toNext.tv_sec; - pToMin->tv_usec = toNext.tv_usec; - } - } - prev = call; - call = call->next; - if(prev->callState >= OO_CALL_CLEAR) - ooEndCall(prev); - }/* while(call) */ - }/* if(gH323ep.callList) */ + if(ooTimerNextTimeout(&call->timerList, &toNext)) + { + if(ooCompareTimeouts(pToMin, &toNext) > 0) + { + pToMin->tv_sec = toNext.tv_sec; + pToMin->tv_usec = toNext.tv_usec; + } + } + + if(call->callState >= OO_CALL_CLEAR && call->callState < OO_CALL_CLEARED) { + ast_mutex_lock(&call->Lock); + ooEndCall(call); + ast_mutex_unlock(&call->Lock); + } else if(call->callState == OO_CALL_CLEARED) { + ast_mutex_lock(&call->Lock); + ooEndCall(call); + ast_mutex_unlock(&call->Lock); + ooStopMonitorCallChannels(call); + } + } return OO_OK; } +int ooMonitorCmdChannels() +{ + int ret=0, nfds=0; + struct timeval toMin, toNext; + struct pollfd pfds[1]; + + gMonitor = TRUE; + + toMin.tv_sec = 3; + toMin.tv_usec = 0; + + while(1) + { + nfds = 0; + ooSetCmdFDSETs(pfds, &nfds); + + if(!gMonitor) { + OOTRACEINFO1("Ending Monitor thread\n"); + break; + } + + + if(nfds == 0) +#ifdef _WIN32 + Sleep(10); +#else + { + toMin.tv_sec = 0; + toMin.tv_usec = 10000; + ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000); + } +#endif + else + ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000); + + if(ret == -1) + { + + OOTRACEERR1("Error in poll ...exiting\n"); + exit(-1); + continue; + } + + toMin.tv_sec = 2; /* 2 sec */ + toMin.tv_usec = 100000; /* 100ms*/ + + ast_mutex_lock(&monitorLock); + if(ooProcessCmdFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK) + { + /* ooStopMonitorCalls(); */ + ast_mutex_unlock(&monitorLock); + continue; + } + ast_mutex_unlock(&monitorLock); + + }/* while(1)*/ + return OO_OK; +} + int ooMonitorChannels() { int ret=0, nfds=0; struct timeval toMin, toNext; - fd_set readfds, writefds; + struct pollfd pfds[2]; gMonitor = TRUE; @@ -723,10 +831,8 @@ while(1) { - FD_ZERO(&readfds); - FD_ZERO(&writefds); nfds = 0; - ooSetFDSETs(&readfds, &writefds, &nfds); + ooSetFDSETs(pfds, &nfds); if(!gMonitor) { OOTRACEINFO1("Ending Monitor thread\n"); @@ -741,24 +847,24 @@ { toMin.tv_sec = 0; toMin.tv_usec = 10000; - ooSocketSelect(1, 0, 0, 0, &toMin); + ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000); } #endif else - ret = ooSocketSelect(nfds, &readfds, &writefds, - NULL, &toMin); + ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000); if(ret == -1) { - OOTRACEERR1("Error in select ...exiting\n"); + OOTRACEERR1("Error in poll ...exiting\n"); exit(-1); } - toMin.tv_sec = 0; + toMin.tv_sec = 2; /* 2 sec */ toMin.tv_usec = 100000; /* 100ms*/ /*This is for test application. Not part of actual stack */ + ast_mutex_lock(&monitorLock); ooTimerFireExpired(&gH323ep.ctxt, &g_TimerList); if(ooTimerNextTimeout(&g_TimerList, &toNext)) { @@ -769,15 +875,97 @@ } } - if(ooProcessFDSETsAndTimers(&readfds, &writefds, &toMin) != OO_OK) + if(ooProcessFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK) { + ast_mutex_unlock(&monitorLock); ooStopMonitorCalls(); continue; } + ast_mutex_unlock(&monitorLock); }/* while(1)*/ return OO_OK; } +int ooMonitorCallChannels(OOH323CallData *call) +{ + int ret=0, nfds=0, zeroloops = 0; +#define MAX_ZERO_LOOP 1020 + struct timeval toMin, toNext; + struct pollfd pfds[5]; + + OOCTXT* pctxt; + + call->Monitor = TRUE; + + toMin.tv_sec = 3; + toMin.tv_usec = 0; + + while(1) + { + if(!call->Monitor) { + OOTRACEINFO1("Ending Call Monitor thread\n"); + break; + } + + nfds = 0; + ooSetCallFDSETs(call, pfds, &nfds); + + + if(nfds == 0) +#ifdef _WIN32 + Sleep(10); +#else + { + if (zeroloops++ > MAX_ZERO_LOOP) { + ooCleanCall(call); + ooStopMonitorCallChannels(call); + break; + } + toMin.tv_sec = 0; + toMin.tv_usec = 10000; + ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000); + } +#endif + else + ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000); + + if(ret == -1) + { + + OOTRACEERR2("Error in poll %d ...exiting\n", errno); + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEARED; + ooCleanCall(call); + ooStopMonitorCallChannels(call); + break; + + } + + toMin.tv_sec = 2; /* 2 sec */ + toMin.tv_usec = 100000; /* 100ms*/ + /*This is for test application. Not part of actual stack */ + + if(ooProcessCallFDSETsAndTimers(call, pfds, nfds, &toMin) != OO_OK) + { + ooStopMonitorCallChannels(call); + continue; + } + + }/* while(1)*/ + + if (call->cmdSock) + ooCloseCallCmdConnection(call); + + ast_mutex_lock(&call->Lock); + ast_mutex_unlock(&call->Lock); + ast_mutex_destroy(&call->Lock); + ast_cond_destroy(&call->gkWait); + pctxt = call->pctxt; + freeContext(pctxt); + free(pctxt); + + return OO_OK; +} int ooH2250Receive(OOH323CallData *call) { @@ -785,9 +973,9 @@ ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN]; int len; Q931Message *pmsg; - OOCTXT *pctxt = &gH323ep.msgctxt; + OOCTXT *pctxt = call->pctxt; + struct timeval timeout; - fd_set readfds; pmsg = (Q931Message*)memAlloc(pctxt, sizeof(Q931Message)); @@ -795,7 +983,8 @@ { OOTRACEERR3("ERROR:Failed to allocate memory for incoming H.2250 message" " (%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->pctxt); return OO_FAILED; } memset(pmsg, 0, sizeof(Q931Message)); @@ -818,7 +1007,7 @@ call->callState = OO_CALL_CLEARED; } - ooFreeQ931Message(pmsg); + ooFreeQ931Message(pctxt, pmsg); return OO_OK; } OOTRACEDBGC3("Receiving H.2250 message (%s, %s)\n", @@ -832,7 +1021,7 @@ OOTRACEERR4("Error: Reading TPKT header for H225 message " "recvLen= %d (%s, %s)\n", recvLen, call->callType, call->callToken); - ooFreeQ931Message(pmsg); + ooFreeQ931Message(pctxt, pmsg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_INVALIDMESSAGE; @@ -863,18 +1052,18 @@ if(total == len) break; /* Complete message is received */ - FD_ZERO(&readfds); - FD_SET(call->pH225Channel->sock, &readfds); + struct pollfd pfds; + pfds.fd = call->pH225Channel->sock; + pfds.events = POLLIN; timeout.tv_sec = 3; timeout.tv_usec = 0; - ret = ooSocketSelect(call->pH225Channel->sock+1, &readfds, NULL, - NULL, &timeout); + ret = ooSocketPoll(&pfds, 1, timeout.tv_sec * 1000); if(ret == -1) { OOTRACEERR3("Error in select while receiving H.2250 message - " "clearing call (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(pmsg); + ooFreeQ931Message(pctxt, pmsg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_TRANSPORTFAILURE; @@ -884,11 +1073,11 @@ } /* If remaining part of the message is not received in 3 seconds exit */ - if(!FD_ISSET(call->pH225Channel->sock, &readfds)) + if(!ooPDRead(&pfds, 1, call->pH225Channel->sock)) { OOTRACEERR3("Error: Incomplete H.2250 message received - clearing " "call (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(pmsg); + ooFreeQ931Message(pctxt, pmsg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_INVALIDMESSAGE; @@ -926,9 +1115,9 @@ ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN]; ASN1BOOL aligned = TRUE; H245Message *pmsg; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->pctxt; struct timeval timeout; - fd_set readfds; pmsg = (H245Message*)memAlloc(pctxt, sizeof(H245Message)); @@ -1015,12 +1204,13 @@ memcpy(message+total, message1, recvLen); total = total + recvLen; if(total == len) break; /* Complete message is received */ - FD_ZERO(&readfds); - FD_SET(call->pH245Channel->sock, &readfds); + + struct pollfd pfds; + pfds.fd = call->pH245Channel->sock; + pfds.events = POLLIN; timeout.tv_sec = 3; timeout.tv_usec = 0; - ret = ooSocketSelect(call->pH245Channel->sock+1, &readfds, NULL, - NULL, &timeout); + ret = ooSocketPoll(&pfds, 1, timeout.tv_sec * 1000); if(ret == -1) { OOTRACEERR3("Error in select...H245 Receive-Clearing call (%s, %s)\n", @@ -1035,7 +1225,7 @@ } /* If remaining part of the message is not received in 3 seconds exit */ - if(!FD_ISSET(call->pH245Channel->sock, &readfds)) + if(!ooPDRead(&pfds, 1, call->pH245Channel->sock)) { OOTRACEERR3("Error: Incomplete h245 message received (%s, %s)\n", call->callType, call->callToken); @@ -1352,8 +1542,8 @@ return OO_FAILED; } - if(gH323ep.h323Callbacks.onOutgoingCall) - gH323ep.h323Callbacks.onOutgoingCall(call); + /* if(gH323ep.h323Callbacks.onOutgoingCall) + gH323ep.h323Callbacks.onOutgoingCall(call); */ break; case OOCallProceeding: OOTRACEINFO3("Sent Message - CallProceeding (%s, %s)\n", call->callType, @@ -1362,8 +1552,8 @@ case OOAlert: OOTRACEINFO3("Sent Message - Alerting (%s, %s) \n", call->callType, call->callToken); - if(gH323ep.h323Callbacks.onAlerting && call->callState < OO_CALL_CLEAR) - gH323ep.h323Callbacks.onAlerting(call); + /* if(gH323ep.h323Callbacks.onAlerting && call->callState < OO_CALL_CLEAR) + gH323ep.h323Callbacks.onAlerting(call); */ break; case OOConnect: OOTRACEINFO3("Sent Message - Connect (%s, %s)\n", call->callType, @@ -1383,6 +1573,8 @@ gH323ep.gkClient->state == GkClientRegistered){ OOTRACEDBGA3("Sending DRQ after sending ReleaseComplete." "(%s, %s)\n", call->callType, call->callToken); + + call->endTime = (H235TimeStamp) time(NULL); ooGkClientSendDisengageRequest(gH323ep.gkClient, call); } } @@ -1702,6 +1894,12 @@ return OO_OK; } +int ooStopMonitorCallChannels(OOH323CallData * call) { + if (call->Monitor) + call->Monitor = FALSE; + /* if (call->cmdSock) + ooCloseCallCmdConnection(call); */ +} int ooStopMonitorCalls() { --- ./channels/ooh323c/src/errmgmt.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/errmgmt.c 2009-05-31 00:18:57.000000000 +0400 @@ -16,6 +16,8 @@ /* Error management functions */ +#include +#include #include #include "ooasn1.h" @@ -86,7 +88,8 @@ { #if defined(_NO_THREADS) || !defined(_NO_MALLOC) if (pErrInfo->parmcnt < ASN_K_MAXERRP) { - char* tmpstr = (char*) ASN1CRTMALLOC0 (strlen(errprm_p)+1); + /* char* tmpstr = (char*) ASN1CRTMALLOC0 (strlen(errprm_p)+1); */ + char* tmpstr = (char*) malloc (strlen(errprm_p)+1); strcpy (tmpstr, errprm_p); pErrInfo->parms[pErrInfo->parmcnt] = tmpstr; pErrInfo->parmcnt++; @@ -114,7 +117,8 @@ int i; for (i = 0; i < pErrInfo->parmcnt; i++) - ASN1CRTFREE0 ((char*)pErrInfo->parms[i]); + /* ASN1CRTFREE0 ((char*)pErrInfo->parms[i]); */ + free ((char*)pErrInfo->parms[i]); #endif pErrInfo->parmcnt = 0; --- ./channels/ooh323c/src/ooCalls.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCalls.c 2009-07-28 22:49:05.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ootrace.h" #include "ootypes.h" #include "ooCalls.h" @@ -28,11 +31,14 @@ /** Global endpoint structure */ extern OOH323EndPoint gH323ep; +extern ast_mutex_t callListLock; +extern ast_mutex_t newCallLock; OOH323CallData* ooCreateCall(char* type, char*callToken) { OOH323CallData *call=NULL; OOCTXT *pctxt=NULL; + OOCTXT *msgctxt=NULL; pctxt = newContext(); if(!pctxt) @@ -40,14 +46,26 @@ OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n"); return NULL; } + msgctxt = newContext(); + if(!msgctxt) + { + OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n"); + return NULL; + } + ast_mutex_lock(&newCallLock); + /* call = (OOH323CallData*)memAlloc(&gH323ep.ctxt, sizeof(OOH323CallData)); */ call = (OOH323CallData*)memAlloc(pctxt, sizeof(OOH323CallData)); + ast_mutex_unlock(&newCallLock); if(!call) { OOTRACEERR1("ERROR:Memory - ooCreateCall - call\n"); return NULL; } - /* memset(call, 0, sizeof(OOH323CallData));*/ + memset(call, 0, sizeof(OOH323CallData)); + ast_cond_init(&call->gkWait, NULL); + ast_mutex_init(&call->Lock); call->pctxt = pctxt; + call->msgctxt = msgctxt; call->callMode = gH323ep.callMode; sprintf(call->callToken, "%s", callToken); sprintf(call->callType, "%s", type); @@ -80,6 +98,10 @@ if (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN)) OO_SETFLAG (call->flags, OO_M_MEDIAWAITFORCONN); + +// May 20090713. Fix it for Video session + + OO_SETFLAG(call->flags, OO_M_AUDIOSESSION); call->callState = OO_CALL_CREATED; call->callEndReason = OO_REASON_UNKNOWN; @@ -158,6 +180,8 @@ int ooAddCallToList(OOH323CallData *call) { + ast_mutex_lock(&callListLock); + if(!gH323ep.callList) { gH323ep.callList = call; @@ -170,6 +194,9 @@ gH323ep.callList->prev = call; gH323ep.callList = call; } + + ast_mutex_unlock(&callListLock); + return OO_OK; } @@ -180,9 +207,16 @@ ooGetCallStateText(call->callState), call->callType, call->callToken); + if(call->callState == OO_CALL_REMOVED) { + OOTRACEINFO2("Call already removed %s\n", + call->callToken); + return OO_OK; + } + if(call->callState == OO_CALL_CLEARED) { ooCleanCall(call); + call->callState = OO_CALL_REMOVED; return OO_OK; } @@ -230,6 +264,11 @@ if(!call) return OO_OK; + ast_mutex_lock(&callListLock); + + OOTRACEINFO3("Removing call %lx: %s\n", call, call->callToken); + + if (!gH323ep.callList) return OO_OK; if(call == gH323ep.callList) { if(!call->next) @@ -244,6 +283,9 @@ if(call->next) call->next->prev = call->prev; } + + ast_mutex_unlock(&callListLock); + return OO_OK; } @@ -314,9 +356,13 @@ gH323ep.h323Callbacks.onCallCleared(call); } - pctxt = call->pctxt; + pctxt = call->msgctxt; freeContext(pctxt); - ASN1CRTFREE0(pctxt); + free(pctxt); + call->msgctxt = NULL; +/* May !!!! Fix it !! */ + /* free(pctxt); */ + return OO_OK; } @@ -489,6 +535,31 @@ /* Used to override global end point capabilities and add call specific capabilities */ +int ooCallAddG726Capability(OOH323CallData *call, int cap, int txframes, + int rxframes, OOBOOL silenceSuppression, int dir, + cb_StartReceiveChannel startReceiveChannel, + cb_StartTransmitChannel startTransmitChannel, + cb_StopReceiveChannel stopReceiveChannel, + cb_StopTransmitChannel stopTransmitChannel) +{ + return ooCapabilityAddSimpleCapability(call, cap, txframes, rxframes, + silenceSuppression, dir, startReceiveChannel, + startTransmitChannel, stopReceiveChannel, + stopTransmitChannel, FALSE); +} +int ooCallAddAMRNBCapability(OOH323CallData *call, int cap, int txframes, + int rxframes, OOBOOL silenceSuppression, int dir, + cb_StartReceiveChannel startReceiveChannel, + cb_StartTransmitChannel startTransmitChannel, + cb_StopReceiveChannel stopReceiveChannel, + cb_StopTransmitChannel stopTransmitChannel) +{ + return ooCapabilityAddSimpleCapability(call, cap, txframes, rxframes, + silenceSuppression, dir, startReceiveChannel, + startTransmitChannel, stopReceiveChannel, + stopTransmitChannel, FALSE); +} + int ooCallAddG7231Capability(OOH323CallData *call, int cap, int txframes, int rxframes, OOBOOL silenceSuppression, int dir, cb_StartReceiveChannel startReceiveChannel, @@ -628,7 +699,7 @@ } -OOH323CallData* ooFindCallByToken(char *callToken) +OOH323CallData* ooFindCallByToken(const char *callToken) { OOH323CallData *call; if(!callToken) @@ -636,9 +707,13 @@ OOTRACEERR1("ERROR:Invalid call token passed - ooFindCallByToken\n"); return NULL; } + + ast_mutex_lock(&callListLock); + if(!gH323ep.callList) { OOTRACEERR1("ERROR: Empty calllist - ooFindCallByToken failed\n"); + ast_mutex_unlock(&callListLock); return NULL; } call = gH323ep.callList; @@ -653,8 +728,14 @@ if(!call) { OOTRACEERR2("ERROR:Call with token %s not found\n", callToken); + ast_mutex_unlock(&callListLock); return NULL; } + + ast_mutex_unlock(&callListLock); + + OOTRACEINFO3("INFO: FinCall returned %lx for call: %s\n", call, callToken); + return call; } @@ -750,6 +831,23 @@ } } } + if(type == OO_CAP_TYPE_DATA) + { + if(!ooGetLogicalChannel(call, 3, dir)) + { + sessionID = 3; + } + else{ + if(call->masterSlaveState == OO_MasterSlave_Master) + sessionID = call->nextSessionID++; + else{ + sessionID = 0; /* Will be assigned by remote */ + OOTRACEDBGC4("Session id for %s channel of type data has to be " + "provided by remote.(%s, %s)\n", dir, call->callType, + call->callToken); + } + } + } return sessionID; } --- ./channels/ooh323c/src/ooCmdChannel.h 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCmdChannel.h 2009-05-30 06:40:48.000000000 +0400 @@ -52,6 +52,7 @@ * @return OO_OK, on success; OO_FAILED, on failure */ EXTERN int ooCreateCmdConnection(); +EXTERN int ooCreateCallCmdConnection(OOH323CallData*); /** * This function is used to close a command channel setup with the stack @@ -60,6 +61,7 @@ * @return OO_OK, on success; OO_FAILED, on failure */ EXTERN int ooCloseCmdConnection(); +EXTERN int ooCloseCallCmdConnection(OOH323CallData*); /** @@ -69,6 +71,7 @@ * @return OO_OK, on success; OO_FAILED, on failure */ EXTERN int ooWriteStackCommand(OOStackCommand *cmd); +EXTERN int ooWriteCallStackCommand(OOH323CallData* call, OOStackCommand *cmd); /** * This function is used by stack thread to read and process stack commands @@ -77,6 +80,7 @@ * @return OO_OK, on success; OO_FAILED, on failure */ EXTERN int ooReadAndProcessStackCommand(); +EXTERN int ooReadAndProcessCallStackCommand(OOH323CallData*); /** --- ./channels/ooh323c/src/ooasn1.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooasn1.h 2009-05-31 00:24:11.000000000 +0400 @@ -22,6 +22,9 @@ #ifndef _OOASN1_H_ #define _OOASN1_H_ +#include +#include + #include #include #include @@ -406,6 +409,7 @@ struct EventHandler* pEventHandler; /* event handler object */ ASN1USINT flags; /* flag bits */ ASN1OCTET spare[2]; + ast_mutex_t pLock; } OOCTXT; /* macros and function prototypes */ @@ -512,8 +516,8 @@ #endif /* EXTERN */ #ifndef _NO_MALLOC -#define ASN1CRTMALLOC0(nbytes) malloc(nbytes) -#define ASN1CRTFREE0(ptr) free(ptr) +/*#define ASN1CRTMALLOC0(nbytes) malloc(nbytes) +#define ASN1CRTFREE0(ptr) free(ptr) */ #else #ifdef _NO_THREADS --- ./channels/ooh323c/src/memheap.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/memheap.c 2009-05-31 00:19:07.000000000 +0400 @@ -13,18 +13,12 @@ * maintain this copyright notice. * *****************************************************************************/ - +#include +#include #include #include "memheap.h" ASN1UINT g_defBlkSize = XM_K_MEMBLKSIZ; -OSMallocFunc g_malloc_func = malloc; -#ifndef _NO_REALLOC -OSReallocFunc g_realloc_func = realloc; -#else -OSReallocFunc g_realloc_func = 0; -#endif -OSFreeFunc g_free_func = free; static OSMemLink* memHeapAddBlock (OSMemLink** ppMemLink, void* pMemBlk, int blockType); @@ -172,6 +166,7 @@ nunits = (((unsigned)(nbytes + 7)) >> 3); pMemHeap = (OSMemHeap*) *ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); ppMemLink = &pMemHeap->phead; /* if size is greater than 2**19, then allocate as RAW block */ @@ -181,17 +176,18 @@ /* allocate raw block */ - data = g_malloc_func (nbytes); + data = malloc (nbytes); if (data == NULL) { return NULL; } pMemLink = memHeapAddBlock (ppMemLink, data, RTMEMMALLOC | RTMEMRAW); if (pMemLink == 0) { - g_free_func (data); + free (data); return NULL; } /* save size of the RAW memory block behind the pMemLink */ *(int*)(((char*)pMemLink) + sizeof (OSMemLink)) = nbytes; + ast_mutex_unlock(&pMemHeap->pLock); return data; } @@ -337,7 +333,7 @@ ((((ASN1UINT)dataUnits) * 8u) + sizeof (OSMemBlk)); } - pmem = (ASN1OCTET*) g_malloc_func (allocSize + sizeof (OSMemLink)); + pmem = (ASN1OCTET*) malloc (allocSize + sizeof (OSMemLink)); if (0 != pmem) { OSMemElemDescr* pElem; @@ -361,7 +357,8 @@ if (memHeapAddBlock (ppMemLink, pMemBlk, RTMEMSTD | RTMEMLINK) == 0) { - g_free_func (pmem); + free (pmem); + ast_mutex_unlock(&pMemHeap->pLock); return NULL; } @@ -374,8 +371,10 @@ CHECKMEMELEM (pMemBlk, pElem); CHECKMEMBLOCK (pMemHeap, pMemBlk); } - else + else { + ast_mutex_unlock(&pMemHeap->pLock); return NULL; + } } RTMEMDIAG2 ("memHeapAlloc: pMemBlk = 0x%x\n", pMemBlk); RTMEMDIAG2 ("memHeapAlloc: pMemBlk->free_x = %d\n", pMemBlk->free_x); @@ -384,6 +383,7 @@ RTMEMDIAG2 ("memHeapAlloc: mem_p = 0x%x\n", mem_p); RTMEMDIAG2 ("memHeapAlloc: sizeof (short) = %d\n", sizeof(short)); + ast_mutex_unlock(&pMemHeap->pLock); return (mem_p); } @@ -407,6 +407,9 @@ if (mem_p == 0 || ppvMemHeap == 0 || *ppvMemHeap == 0) return; pMemHeap = *(OSMemHeap**)ppvMemHeap; + + ast_mutex_lock(&pMemHeap->pLock); + ppMemLink = &pMemHeap->phead; /* look for chain of RAW blocks first */ @@ -434,13 +437,14 @@ if ((pMemLink->blockType & RTMEMLINK) && (pMemLink->blockType & RTMEMMALLOC)) { - g_free_func (pMemLink); + free (pMemLink); } else { if (pMemLink->blockType & RTMEMMALLOC) - g_free_func (pMemLink->pMemBlk); - g_free_func (pMemLink); + free (pMemLink->pMemBlk); + free (pMemLink); } + ast_mutex_unlock(&pMemHeap->pLock); return; } pPrevMemLink = pMemLink; @@ -455,6 +459,7 @@ if (ISFREE (pElem)) { /* already freed! */ RTMEMDIAG2 ("memHeapFreePtr: " "the element 0x%x is already freed!\n", pElem); + ast_mutex_unlock(&pMemHeap->pLock); return; } @@ -548,11 +553,11 @@ FILLFREEMEM (pMemBlk->plink, sizeof (*pMemBlk->plink)); FILLFREEMEM (pMemBlk->data, (pMemBlk->nunits * 8u)); - g_free_func (pMemBlk->plink); + free (pMemBlk->plink); if (!(blockType & RTMEMLINK)) { FILLFREEMEM (pMemBlk, sizeof (*pMemBlk)); - g_free_func (pMemBlk); + free (pMemBlk); } RTMEMDIAG2 ("memHeapFreePtr: pMemBlk = 0x%x was freed\n", pMemBlk); @@ -642,6 +647,7 @@ CHECKMEMELEM (pMemBlk, pElem); CHECKMEMBLOCK (pMemHeap, pMemBlk); } + ast_mutex_unlock(&pMemHeap->pLock); } static void initNewFreeElement (OSMemBlk* pMemBlk, @@ -742,8 +748,8 @@ pMemLink->pMemBlk == mem_p) { if (pMemLink->blockType & RTMEMMALLOC) - if (g_realloc_func != 0) { - void *newMemBlk = g_realloc_func (pMemLink->pMemBlk, nbytes_); + if (1) { + void *newMemBlk = realloc (pMemLink->pMemBlk, nbytes_); if (newMemBlk == 0) return 0; pMemLink->pMemBlk = newMemBlk; @@ -754,7 +760,7 @@ int oldSize = *(int*)(((char*)pMemLink) + sizeof (OSMemLink)); if (oldSize == -1) return 0; - newBuf = (ASN1OCTET*)g_malloc_func (nbytes_); + newBuf = (ASN1OCTET*) malloc (nbytes_); if (newBuf == 0) return 0; memcpy (newBuf, pMemLink->pMemBlk, ASN1MIN (oldSize, nbytes_)); @@ -994,6 +1000,8 @@ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return; pMemHeap = *(OSMemHeap**)ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); + pMemLink = pMemHeap->phead; RTMEMDIAG2 ("memHeapFreeAll: pMemHeap = 0x%x\n", pMemHeap); @@ -1045,10 +1053,11 @@ if (((pMemLink2->blockType & RTMEMSTD) || (pMemLink2->blockType & RTMEMMALLOC)) && !(pMemLink2->blockType & RTMEMLINK)) - g_free_func (pMemLink2->pMemBlk); - g_free_func (pMemLink2); + free (pMemLink2->pMemBlk); + free (pMemLink2); } } + ast_mutex_unlock(&pMemHeap->pLock); } /* increments internal refCnt. use memHeapRelease to decrement and release */ @@ -1058,7 +1067,9 @@ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return; pMemHeap = *(OSMemHeap**)ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); pMemHeap->refCnt++; + ast_mutex_unlock(&pMemHeap->pLock); } /* Frees all memory and heap structure as well (if was allocated) */ @@ -1106,6 +1117,9 @@ return 0; pMemHeap = *(OSMemHeap**)ppvMemHeap; + + ast_mutex_lock(&pMemHeap->pLock); + pMemLink = pMemHeap->phead; /* look for chain of RAW blocks first */ @@ -1128,6 +1142,8 @@ if (ISFREE (pElem)) { /* already freed! */ RTMEMDIAG2 ("memHeapMarkSaved: the element 0x%x is " "already free!\n", pElem); + + ast_mutex_unlock(&pMemHeap->pLock); return 0; } @@ -1147,12 +1163,15 @@ nsaved = pMemBlk->nsaved; } else + ast_mutex_unlock(&pMemHeap->pLock); return 0; } if (saved && nsaved > 0) pMemLink->blockType |= RTMEMSAVED; else if (nsaved == 0) pMemLink->blockType &= (~RTMEMSAVED); + + ast_mutex_unlock(&pMemHeap->pLock); return pMemLink->pMemBlk; } @@ -1167,6 +1186,8 @@ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return; pMemHeap = *(OSMemHeap**)ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); + pMemLink = pMemHeap->phead; TRACEFREE (pMemHeap, "memHeapReset\n\n"); while (pMemLink) { @@ -1190,6 +1211,7 @@ } pMemLink = pMemLink->pnext; } + ast_mutex_unlock(&pMemHeap->pLock); } /* add memory block to list */ @@ -1206,7 +1228,7 @@ if (blockType & RTMEMLINK) pMemLink = (OSMemLink*) (((ASN1OCTET*)pMemBlk) - sizeof (OSMemLink)); else { - pMemLink = (OSMemLink*) g_malloc_func ( + pMemLink = (OSMemLink*) malloc ( sizeof(OSMemLink) + sizeof (int)); if (pMemLink == 0) return 0; /* An extra integer is necessary to save a size of a RAW memory block @@ -1257,6 +1279,8 @@ return 0; pMemHeap = *(OSMemHeap**)ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); + pMemLink = pMemHeap->phead; for (; pMemLink != 0; pMemLink = pMemLink->pnext) { @@ -1264,8 +1288,10 @@ /* if RAW block, the pointer should be stored in pMemBlk */ - if (pMemLink->pMemBlk == mem_p) + if (pMemLink->pMemBlk == mem_p) { + ast_mutex_unlock(&pMemHeap->pLock); return 1; + } } else { OSMemBlk* pMemBlk = (OSMemBlk*)pMemLink->pMemBlk; @@ -1281,12 +1307,16 @@ for (; pElem != 0; pElem = GETNEXT (pElem)) { void* curMem_p = (void*) pElem_data (pElem); - if (curMem_p == mem_p && !ISFREE (pElem)) + if (curMem_p == mem_p && !ISFREE (pElem)) { + ast_mutex_unlock(&pMemHeap->pLock); return 1; + } } } } } + + ast_mutex_unlock(&pMemHeap->pLock); return 0; } @@ -1301,6 +1331,8 @@ memHeapCreate (ppvMemHeap); pMemHeap = *(OSMemHeap**)ppvMemHeap; + ast_mutex_lock(&pMemHeap->pLock); + switch (propId) { case OSRTMH_PROPID_DEFBLKSIZE: pMemHeap->defBlkSize = *(ASN1UINT*)pProp; @@ -1312,6 +1344,7 @@ pMemHeap->flags &= ((~(*(ASN1UINT*)pProp)) | RT_MH_INTERNALMASK); break; } + ast_mutex_unlock(&pMemHeap->pLock); } int memHeapCreate (void** ppvMemHeap) @@ -1319,12 +1352,13 @@ OSMemHeap* pMemHeap; if (ppvMemHeap == 0) return ASN_E_INVPARAM; - pMemHeap = (OSMemHeap*) g_malloc_func (sizeof (OSMemHeap)); + pMemHeap = (OSMemHeap*) malloc (sizeof (OSMemHeap)); if (pMemHeap == NULL) return ASN_E_NOMEM; memset (pMemHeap, 0, sizeof (OSMemHeap)); pMemHeap->defBlkSize = g_defBlkSize; pMemHeap->refCnt = 1; pMemHeap->flags = RT_MH_FREEHEAPDESC; + ast_mutex_init(&pMemHeap->pLock); *ppvMemHeap = (void*)pMemHeap; return ASN_OK; } --- ./channels/ooh323c/src/rtctype.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/rtctype.c 2009-05-31 00:23:24.000000000 +0400 @@ -16,6 +16,9 @@ /* Run-time ctype substitution */ +#include +#include + #include "ooasn1.h" #include "rtctype.h" --- ./channels/ooh323c/src/ooStackCmds.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooStackCmds.h 2009-07-28 22:49:05.000000000 +0400 @@ -65,7 +65,9 @@ OO_CMD_HANGCALL, /*!< Terminate call */ OO_CMD_SENDDIGIT, /*!< Send dtmf */ OO_CMD_MANUALRINGBACK, /*!< Send Alerting - ringback */ - OO_CMD_STOPMONITOR /*!< Stop the event monitor */ + OO_CMD_MANUALPROGRESS, /*!< Send progress */ + OO_CMD_STOPMONITOR, /*!< Stop the event monitor */ + OO_CMD_REQMODE /*!< Request new mode */ } OOStackCmdID; @@ -76,8 +78,11 @@ typedef struct OOStackCommand { OOStackCmdID type; void* param1; + int plen1; void* param2; + int plen2; void* param3; + int plen3; } OOStackCommand; #define ooCommand OOStackCommand; @@ -105,6 +110,7 @@ * @return Returns OOStkCmdStat value indication success or failure. */ EXTERN OOStkCmdStat ooManualRingback(const char *callToken); +EXTERN OOStkCmdStat ooManualProgress(const char *callToken); /** * This function is used to answer a call @@ -131,7 +137,7 @@ * * @return Returns OOStkCmdStat value indication success or failure. */ -EXTERN OOStkCmdStat ooHangCall(const char* callToken, OOCallClearReason reason); +EXTERN OOStkCmdStat ooHangCall(const char* callToken, OOCallClearReason reason, int q931cause); /** * This command function can be used by an user application to send a DTMF --- ./channels/ooh323c/src/ooCapability.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCapability.h 2009-07-29 00:25:40.000000000 +0400 @@ -33,6 +33,7 @@ supported */ typedef enum OOCapabilities{ OO_CAP_AUDIO_BASE = 0, + OO_G726 = 1, OO_G711ALAW64K = 2, OO_G711ALAW56K = 3, OO_G711ULAW64K = 4, @@ -44,8 +45,13 @@ OO_G728 = 10, OO_G729 = 11, OO_G729A = 12, +#if 0 OO_IS11172_AUDIO = 13, OO_IS13818_AUDIO = 14, +#else + OO_AMRNB = 13, + OO_G726AAL2 = 14, +#endif OO_G729B = 15, OO_G729AB = 16, OO_G7231C = 17, @@ -65,7 +71,8 @@ OO_H263VIDEO = 31, OO_IS11172VIDEO = 32, /* mpeg */ OO_GENERICVIDEO = 33, - OO_EXTELEMVIDEO = 34 + OO_EXTELEMVIDEO = 34, + OO_T38 = 35 } OOCapabilities; @@ -579,6 +586,8 @@ */ struct H245AudioCapability* ooCapabilityCreateSimpleCapability (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir); +struct H245AudioCapability* ooCapabilityCreateNonStandardCapability + (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir); /** @@ -651,6 +660,14 @@ ooH323EpCapability* ooIsDataTypeSupported (struct OOH323CallData *call, H245DataType *data, int dir); +/* fill t.38 application data */ +struct H245DataApplicationCapability_application* ooCreateT38ApplicationData + (OOCTXT* pctxt, H245DataApplicationCapability_application *app); + +/* create t.38 capability */ +struct H245DataApplicationCapability* ooCapabilityCreateT38Capability + (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir); + /** * This function is used to clear the capability preference order. * @param call Handle to call, if capability preference order for call @@ -714,6 +731,9 @@ EXTERN const char* ooGetCapTypeText (OOCapabilities cap); +EXTERN int epCapIsPreferred(struct OOH323CallData *call, ooH323EpCapability *epCap); + + /** * @} */ --- ./channels/ooh323c/src/ooh323ep.c 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh323ep.c 2009-07-28 22:49:05.000000000 +0400 @@ -13,6 +13,9 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include + #include "ooh323ep.h" #include "ootrace.h" #include "ooCalls.h" @@ -23,6 +26,10 @@ /** Global endpoint structure */ ooEndPoint gH323ep; +ast_mutex_t monitorLock; +ast_mutex_t callListLock; +ast_mutex_t newCallLock; +ast_mutex_t bindPortLock; extern DList g_TimerList; @@ -104,6 +111,10 @@ gH323ep.myCaps = NULL; gH323ep.noOfCaps = 0; gH323ep.callList = NULL; + ast_mutex_init(&monitorLock); + ast_mutex_init(&callListLock); + ast_mutex_init(&newCallLock); + ast_mutex_init(&bindPortLock); gH323ep.dtmfmode = 0; gH323ep.callingPartyNumber[0]='\0'; gH323ep.callMode = callMode; @@ -135,6 +146,16 @@ return OO_OK; } +EXTERN int ooH323EpSetVersionInfo(int t35cc, int t35ext, int manc, char* prodid, char* verid) { + + if (t35cc) gH323ep.t35CountryCode = t35cc; + if (t35ext) gH323ep.t35Extension = t35ext; + if (manc) gH323ep.manufacturerCode = manc; + if (prodid != NULL && prodid[0]) gH323ep.productID = prodid; + if (verid != NULL && verid[0]) gH323ep.versionID = verid; +} + + int ooH323EpSetLocalAddress(const char* localip, int listenport) { @@ -316,6 +337,7 @@ { gH323ep.h323Callbacks.onNewCallCreated = h323Callbacks.onNewCallCreated; gH323ep.h323Callbacks.onAlerting = h323Callbacks.onAlerting; + gH323ep.h323Callbacks.onProgress = h323Callbacks.onProgress; gH323ep.h323Callbacks.onIncomingCall = h323Callbacks.onIncomingCall; gH323ep.h323Callbacks.onOutgoingCall = h323Callbacks.onOutgoingCall; gH323ep.h323Callbacks.onCallEstablished = h323Callbacks.onCallEstablished; @@ -323,6 +345,7 @@ gH323ep.h323Callbacks.onCallCleared = h323Callbacks.onCallCleared; gH323ep.h323Callbacks.openLogicalChannels = h323Callbacks.openLogicalChannels; gH323ep.h323Callbacks.onReceivedDTMF = h323Callbacks.onReceivedDTMF; + gH323ep.h323Callbacks.onModeChanged = h323Callbacks.onModeChanged; return OO_OK; } @@ -364,6 +387,7 @@ } freeContext(&(gH323ep.ctxt)); + freeContext(&(gH323ep.msgctxt)); OO_CLRFLAG(gH323ep.flags, OO_M_ENDPOINTCREATED); } @@ -443,6 +467,15 @@ return OO_OK; } +int ooH323EpTryBeMaster(int m) +{ + if (m) + OO_SETFLAG(gH323ep.flags, OO_M_TRYBEMASTER); + else + OO_CLRFLAG(gH323ep.flags, OO_M_TRYBEMASTER); + return OO_OK; +} + int ooH323EpSetTermType(int value) { gH323ep.termType = value; @@ -626,6 +659,31 @@ stopTransmitChannel, FALSE); } +int ooH323EpAddG726Capability(int cap, int txframes, int rxframes, + OOBOOL silenceSuppression, int dir, + cb_StartReceiveChannel startReceiveChannel, + cb_StartTransmitChannel startTransmitChannel, + cb_StopReceiveChannel stopReceiveChannel, + cb_StopTransmitChannel stopTransmitChannel) +{ + return ooCapabilityAddSimpleCapability(NULL, cap, txframes, rxframes, + silenceSuppression, dir, startReceiveChannel, + startTransmitChannel, stopReceiveChannel, + stopTransmitChannel, FALSE); +} +int ooH323EpAddAMRNBCapability(int cap, int txframes, int rxframes, + OOBOOL silenceSuppression, int dir, + cb_StartReceiveChannel startReceiveChannel, + cb_StartTransmitChannel startTransmitChannel, + cb_StopReceiveChannel stopReceiveChannel, + cb_StopTransmitChannel stopTransmitChannel) +{ + return ooCapabilityAddSimpleCapability(NULL, cap, txframes, rxframes, + silenceSuppression, dir, startReceiveChannel, + startTransmitChannel, stopReceiveChannel, + stopTransmitChannel, FALSE); +} + int ooH323EpAddGSMCapability(int cap, ASN1USINT framesPerPkt, OOBOOL comfortNoise, OOBOOL scrambled, int dir, cb_StartReceiveChannel startReceiveChannel, --- ./channels/ooh323c/src/ooStackCmds.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooStackCmds.c 2009-07-28 22:49:05.000000000 +0400 @@ -13,6 +13,8 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include #include "ooStackCmds.h" #include "ooh323ep.h" @@ -20,18 +22,21 @@ #include "ooCmdChannel.h" extern OOSOCKET gCmdChan; +extern ast_mutex_t newCallLock; + +static int counter = 1; int ooGenerateOutgoingCallToken (char *callToken, size_t size) { - static int counter = 1; char aCallToken[200]; int ret = 0; - + ast_mutex_lock(&newCallLock); sprintf (aCallToken, "ooh323c_o_%d", counter++); if (counter > OO_MAX_CALL_TOKEN) counter = 1; + ast_mutex_unlock(&newCallLock); if ((strlen(aCallToken)+1) < size) strcpy (callToken, aCallToken); @@ -42,6 +47,14 @@ return ret; } +int isRunning(char *callToken) { + OOH323CallData *call; + + if((call = ooFindCallByToken(callToken))) + if (call->Monitor) + return 1; + return 0; +} OOStkCmdStat ooMakeCall (const char* dest, char* callToken, size_t bufsiz, ooCallOptions *opts) @@ -108,18 +121,102 @@ return OO_STKCMD_SUCCESS; } +OOStkCmdStat ooRunCall + (const char* dest, char* callToken, size_t bufsiz, ooCallOptions *opts) +{ + OOStackCommand cmd; + OOH323CallData *call; + + if(!callToken) + { + return OO_STKCMD_INVALIDPARAM; + } + + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) + { + if(ooCreateCallCmdConnection(call) != OO_OK) + return OO_STKCMD_CONNECTIONERR; + } + + if(!callToken) + return OO_STKCMD_INVALIDPARAM; + + + memset(&cmd, 0, sizeof(OOStackCommand)); + cmd.type = OO_CMD_MAKECALL; + cmd.param1 = (void*) malloc(strlen(dest)+1); + if(!cmd.param1) + { + return OO_STKCMD_MEMERR; + } + strcpy((char*)cmd.param1, dest); + cmd.plen1 = strlen(dest); + + + cmd.param2 = (void*) malloc(strlen(callToken)+1); + if(!cmd.param2) + { + free(cmd.param1); + return OO_STKCMD_MEMERR; + } + + strcpy((char*)cmd.param2, callToken); + cmd.plen2 = strlen(callToken); + + if(!opts) + { + cmd.param3 = 0; + } + else { + cmd.param3 = (void*) malloc(sizeof(ooCallOptions)); + if(!cmd.param3) + { + free(cmd.param1); + free(cmd.param2); + return OO_STKCMD_MEMERR; + } + memcpy((void*)cmd.param3, opts, sizeof(ooCallOptions)); + cmd.plen3 = sizeof(ooCallOptions); + } + + if(ooWriteCallStackCommand(call, &cmd) != OO_OK) + { + free(cmd.param1); + free(cmd.param2); + if(cmd.param3) free(cmd.param3); + return OO_STKCMD_WRITEERR; + } + + + free(cmd.param1); + free(cmd.param2); + if(cmd.param3) free(cmd.param3); + + return OO_STKCMD_SUCCESS; +} + OOStkCmdStat ooManualRingback(const char *callToken) { OOStackCommand cmd; + OOH323CallData *call; + if(!callToken) { return OO_STKCMD_INVALIDPARAM; } - if(gCmdChan == 0) + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) { - if(ooCreateCmdConnection() != OO_OK) + if(ooCreateCallCmdConnection(call) != OO_OK) return OO_STKCMD_CONNECTIONERR; } @@ -131,28 +228,77 @@ return OO_STKCMD_MEMERR; } strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); - if(ooWriteStackCommand(&cmd) != OO_OK) + if(ooWriteCallStackCommand(call,&cmd) != OO_OK) { free(cmd.param1); return OO_STKCMD_WRITEERR; } + free(cmd.param1); + + return OO_STKCMD_SUCCESS; +} + +OOStkCmdStat ooManualProgress(const char *callToken) +{ + OOStackCommand cmd; + OOH323CallData *call; + + if(!callToken) + { + return OO_STKCMD_INVALIDPARAM; + } + + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) + { + if(ooCreateCallCmdConnection(call) != OO_OK) + return OO_STKCMD_CONNECTIONERR; + } + + memset(&cmd, 0, sizeof(OOStackCommand)); + cmd.type = OO_CMD_MANUALPROGRESS; + cmd.param1 = (void*) malloc(strlen(callToken)+1); + if(!cmd.param1) + { + return OO_STKCMD_MEMERR; + } + strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); + + if(ooWriteCallStackCommand(call, &cmd) != OO_OK) + { + free(cmd.param1); + return OO_STKCMD_WRITEERR; + } + + free(cmd.param1); + return OO_STKCMD_SUCCESS; } OOStkCmdStat ooAnswerCall(const char *callToken) { OOStackCommand cmd; + OOH323CallData *call; if(!callToken) { return OO_STKCMD_INVALIDPARAM; } - if(gCmdChan == 0) + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) { - if(ooCreateCmdConnection() != OO_OK) + if(ooCreateCallCmdConnection(call) != OO_OK) return OO_STKCMD_CONNECTIONERR; } @@ -165,31 +311,38 @@ return OO_STKCMD_MEMERR; } strcpy((char*)cmd.param1, callToken); - - if(ooWriteStackCommand(&cmd) != OO_OK) + cmd.plen1 = strlen(callToken); + + if(ooWriteCallStackCommand(call, &cmd) != OO_OK) { free(cmd.param1); return OO_STKCMD_WRITEERR; } + free(cmd.param1); + return OO_STKCMD_SUCCESS; } OOStkCmdStat ooForwardCall(const char* callToken, char *dest) { OOStackCommand cmd; + OOH323CallData *call; if(!callToken || !dest) { return OO_STKCMD_INVALIDPARAM; } - if(gCmdChan == 0) + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) { - if(ooCreateCmdConnection() != OO_OK) + if(ooCreateCallCmdConnection(call) != OO_OK) return OO_STKCMD_CONNECTIONERR; } - memset(&cmd, 0, sizeof(OOStackCommand)); cmd.type = OO_CMD_FWDCALL; @@ -202,31 +355,41 @@ return OO_STKCMD_MEMERR; } strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); strcpy((char*)cmd.param2, dest); + cmd.plen2 = strlen(dest); - if(ooWriteStackCommand(&cmd) != OO_OK) + if(ooWriteCallStackCommand(call, &cmd) != OO_OK) { free(cmd.param1); free(cmd.param2); return OO_STKCMD_WRITEERR; } + free(cmd.param1); + free(cmd.param2); return OO_STKCMD_SUCCESS; } -OOStkCmdStat ooHangCall(const char* callToken, OOCallClearReason reason) +OOStkCmdStat ooHangCall(const char* callToken, OOCallClearReason reason, int q931cause) { OOStackCommand cmd; + OOH323CallData *call; + if(!callToken) { return OO_STKCMD_INVALIDPARAM; } - if(gCmdChan == 0) + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) { - if(ooCreateCmdConnection() != OO_OK) + if(ooCreateCallCmdConnection(call) != OO_OK) return OO_STKCMD_CONNECTIONERR; } @@ -234,21 +397,31 @@ cmd.type = OO_CMD_HANGCALL; cmd.param1 = (void*) malloc(strlen(callToken)+1); cmd.param2 = (void*) malloc(sizeof(OOCallClearReason)); - if(!cmd.param1 || !cmd.param2) + cmd.param3 = (void*) malloc(sizeof(int)); + if(!cmd.param1 || !cmd.param2 || !cmd.param3) { if(cmd.param1) free(cmd.param1); /* Release memory */ if(cmd.param2) free(cmd.param2); + if(cmd.param3) free(cmd.param3); return OO_STKCMD_MEMERR; } strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); *((OOCallClearReason*)cmd.param2) = reason; + cmd.plen2 = sizeof(OOCallClearReason); + *(int *)cmd.param3 = q931cause; + cmd.plen3 = sizeof(int); - if(ooWriteStackCommand(&cmd) != OO_OK) + if(ooWriteCallStackCommand(call, &cmd) != OO_OK) { free(cmd.param1); free(cmd.param2); + free(cmd.param3); return OO_STKCMD_WRITEERR; } + free(cmd.param1); + free(cmd.param2); + free(cmd.param3); return OO_STKCMD_SUCCESS; } @@ -276,15 +449,20 @@ OOStkCmdStat ooSendDTMFDigit(const char *callToken, const char* dtmf) { OOStackCommand cmd; + OOH323CallData *call; if(!callToken) { return OO_STKCMD_INVALIDPARAM; } - if(gCmdChan == 0) + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) { - if(ooCreateCmdConnection() != OO_OK) + if(ooCreateCallCmdConnection(call) != OO_OK) return OO_STKCMD_CONNECTIONERR; } @@ -300,14 +478,66 @@ return OO_STKCMD_MEMERR; } strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); strcpy((char*)cmd.param2, dtmf); + cmd.plen2 = strlen(dtmf); - if(ooWriteStackCommand(&cmd) != OO_OK) + if(ooWriteCallStackCommand(call,&cmd) != OO_OK) + { + free(cmd.param1); + free(cmd.param2); + return OO_STKCMD_WRITEERR; + } + free(cmd.param1); + free(cmd.param2); + + return OO_STKCMD_SUCCESS; +} + +OOStkCmdStat ooRequestChangeMode(const char *callToken, int isT38Mode) +{ + OOStackCommand cmd; + OOH323CallData *call; + + if(!callToken) + { + return OO_STKCMD_INVALIDPARAM; + } + + if(!(call = ooFindCallByToken(callToken))) { + return OO_STKCMD_INVALIDPARAM; + } + + if(call->CmdChan == 0) + { + if(ooCreateCallCmdConnection(call) != OO_OK) + return OO_STKCMD_CONNECTIONERR; + } + + memset(&cmd, 0, sizeof(OOStackCommand)); + cmd.type = OO_CMD_REQMODE; + + cmd.param1 = (void*) malloc(strlen(callToken)+1); + cmd.param2 = (void*) malloc(sizeof(int)); + if(!cmd.param1 || !cmd.param2) + { + if(cmd.param1) free(cmd.param1); /* Release memory */ + if(cmd.param2) free(cmd.param2); + return OO_STKCMD_MEMERR; + } + strcpy((char*)cmd.param1, callToken); + cmd.plen1 = strlen(callToken); + *((int *) cmd.param2) = isT38Mode; + cmd.plen2 = sizeof(int); + + if(ooWriteCallStackCommand(call,&cmd) != OO_OK) { free(cmd.param1); free(cmd.param2); return OO_STKCMD_WRITEERR; } + free(cmd.param1); + free(cmd.param2); return OO_STKCMD_SUCCESS; } --- ./channels/ooh323c/src/ooSocket.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooSocket.h 2009-06-30 04:33:07.000000000 +0400 @@ -331,6 +331,11 @@ EXTERN int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval * timeout); +EXTERN int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout); + +EXTERN int ooPDRead(struct pollfd *pfds, int nfds, int fd); +EXTERN int ooPDWrite(struct pollfd *pfds, int nfds, int fd); + /** * This function converts the string with IP address to a double word * representation. The converted address may be used with the ::rtSocketBind --- ./channels/ooh323c/src/ooUtils.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooUtils.c 2009-05-31 00:14:40.000000000 +0400 @@ -14,6 +14,8 @@ * *****************************************************************************/ +#include +#include #include "ooUtils.h" const char* ooUtilsGetText (OOUINT32 idx, const char** table, size_t tabsiz) --- ./channels/ooh323c/src/ooh323.c 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh323.c 2009-07-28 22:49:05.000000000 +0400 @@ -14,6 +14,10 @@ * *****************************************************************************/ +#include +#include +#include + #include "ootypes.h" #include "ooq931.h" #include "ootrace.h" @@ -93,6 +97,7 @@ if(call->callEndReason == OO_REASON_UNKNOWN) call->callEndReason = ooGetCallClearReasonFromCauseAndReasonCode(cause, reasonCode); + call->q931cause = cause; #if 0 if (q931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent && q931Msg->userInfo->h323_uu_pdu.h245Tunneling && @@ -469,6 +474,26 @@ } if(!strcmp(pChannel->dir, "transmit")) { + /* May 20090728 */ + if (!epCapIsPreferred(call, pChannel->chanCap)) { + if(call->localTermCapState == OO_LocalTermCapExchange_Idle) { + ret = ooSendTermCapMsg(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", + call->callType, call->callToken); + return ret; + } + } + if(call->masterSlaveState == OO_MasterSlave_Idle) { + ret = ooSendMasterSlaveDetermination(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Master-slave determination message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + } + } + if(olc->forwardLogicalChannelParameters.multiplexParameters.t != T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) { @@ -666,6 +691,26 @@ } if(!strcmp(pChannel->dir, "transmit")) { + /* May 20090728 */ + if (!epCapIsPreferred(call, pChannel->chanCap)) { + if(call->localTermCapState == OO_LocalTermCapExchange_Idle) { + ret = ooSendTermCapMsg(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", + call->callType, call->callToken); + return ret; + } + } + if(call->masterSlaveState == OO_MasterSlave_Idle) { + ret = ooSendMasterSlaveDetermination(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Master-slave determination message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + } + } + if(olc->forwardLogicalChannelParameters.multiplexParameters.t != T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) { @@ -711,11 +756,11 @@ return OO_FAILED; } pChannel->chanCap->startTransmitChannel(call, pChannel); - } - /* Mark the current channel as established and close all other - logical channels with same session id and in same direction. - */ - ooOnLogicalChannelEstablished(call, pChannel); + /* Mark the current channel as established and close all other + logical channels with same session id and in same direction. + */ + ooOnLogicalChannelEstablished(call, pChannel); + } } finishPrint(); removeEventHandler(call->pctxt); @@ -758,6 +803,225 @@ return OO_FAILED; } } + + + return OO_OK; +} + +int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg) +{ + H225Progress_UUIE *progress=NULL; + H245OpenLogicalChannel* olc; + ASN1OCTET msgbuf[MAXMSGLEN]; + ooLogicalChannel * pChannel = NULL; + H245H2250LogicalChannelParameters * h2250lcp = NULL; + int i=0, ret=0; + + + if(!q931Msg->userInfo) + { + OOTRACEERR3("ERROR:No User-User IE in received Progress message." + " (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + progress = q931Msg->userInfo->h323_uu_pdu.h323_message_body.u.progress; + if(progress == NULL) + { + OOTRACEERR3("Error: Received Progress message does not have " + "progress UUIE (%s, %s)\n", call->callType, + call->callToken); + /* Mark call for clearing */ + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + /*Handle fast-start */ + if(OO_TESTFLAG (call->flags, OO_M_FASTSTART) && + !OO_TESTFLAG(call->flags, OO_M_FASTSTARTANSWERED)) + { + if(progress->m.fastStartPresent) + { + /* For printing the decoded message to log, initialize handler. */ + initializePrintHandler(&printHandler, "FastStart Elements"); + + /* Set print handler */ + setEventHandler (call->pctxt, &printHandler); + + for(i=0; i<(int)progress->fastStart.n; i++) + { + olc = NULL; + + olc = (H245OpenLogicalChannel*)memAlloc(call->pctxt, + sizeof(H245OpenLogicalChannel)); + if(!olc) + { + OOTRACEERR3("ERROR:Memory - ooOnReceivedProgress - olc" + "(%s, %s)\n", call->callType, call->callToken); + /*Mark call for clearing */ + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_LOCAL_CLEARED; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + memset(olc, 0, sizeof(H245OpenLogicalChannel)); + memcpy(msgbuf, progress->fastStart.elem[i].data, + progress->fastStart.elem[i].numocts); + setPERBuffer(call->pctxt, msgbuf, + progress->fastStart.elem[i].numocts, 1); + ret = asn1PD_H245OpenLogicalChannel(call->pctxt, olc); + if(ret != ASN_OK) + { + OOTRACEERR3("ERROR:Failed to decode fast start olc element " + "(%s, %s)\n", call->callType, call->callToken); + /* Mark call for clearing */ + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + + dListAppend(call->pctxt, &call->remoteFastStartOLCs, olc); + + pChannel = ooFindLogicalChannelByOLC(call, olc); + if(!pChannel) + { + OOTRACEERR4("ERROR: Logical Channel %d not found, fast start. " + "(%s, %s)\n", + olc->forwardLogicalChannelNumber, call->callType, + call->callToken); + return OO_FAILED; + } + if(pChannel->channelNo != olc->forwardLogicalChannelNumber) + { + OOTRACEINFO5("Remote endpoint changed forwardLogicalChannel" + "Number from %d to %d (%s, %s)\n", + pChannel->channelNo, + olc->forwardLogicalChannelNumber, call->callType, + call->callToken); + pChannel->channelNo = olc->forwardLogicalChannelNumber; + } + if(!strcmp(pChannel->dir, "transmit")) + { + /* May 20090728 */ + if (!epCapIsPreferred(call, pChannel->chanCap)) { + if(call->localTermCapState == OO_LocalTermCapExchange_Idle) { + ret = ooSendTermCapMsg(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", + call->callType, call->callToken); + return ret; + } + } + if(call->masterSlaveState == OO_MasterSlave_Idle) { + ret = ooSendMasterSlaveDetermination(call); + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Sending Master-slave determination message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + } + } + + if(olc->forwardLogicalChannelParameters.multiplexParameters.t != + T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) + { + OOTRACEERR4("ERROR:Unknown multiplex parameter type for " + "channel %d (%s, %s)\n", + olc->forwardLogicalChannelNumber, call->callType, + call->callToken); + continue; + } + + /* Extract the remote media endpoint address */ + h2250lcp = olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters; + if(!h2250lcp) + { + OOTRACEERR3("ERROR:Invalid OLC received in fast start. No " + "forward Logical Channel Parameters found. " + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + if(!h2250lcp->m.mediaChannelPresent) + { + OOTRACEERR3("ERROR:Invalid OLC received in fast start. No " + "reverse media channel information found." + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + ret = ooGetIpPortFromH245TransportAddress(call, + &h2250lcp->mediaChannel, pChannel->remoteIP, + &pChannel->remoteMediaPort); + + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Unsupported media channel address type " + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + + if(!pChannel->chanCap->startTransmitChannel) + { + OOTRACEERR3("ERROR:No callback registered to start transmit " + "channel (%s, %s)\n",call->callType, + call->callToken); + return OO_FAILED; + } + pChannel->chanCap->startTransmitChannel(call, pChannel); + } + /* Mark the current channel as established and close all other + logical channels with same session id and in same direction. + */ + ooOnLogicalChannelEstablished(call, pChannel); + } + finishPrint(); + removeEventHandler(call->pctxt); + OO_SETFLAG(call->flags, OO_M_FASTSTARTANSWERED); + } + + } + + /* Retrieve the H.245 control channel address from the connect msg */ + if(q931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent && + q931Msg->userInfo->h323_uu_pdu.h245Tunneling && + progress->m.h245AddressPresent) { + OOTRACEINFO3("Tunneling and h245address provided." + "Giving preference to Tunneling (%s, %s)\n", + call->callType, call->callToken); + } + else if(progress->m.h245AddressPresent) + { + if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + { + OO_CLRFLAG (call->flags, OO_M_TUNNELING); + OOTRACEINFO3("Tunneling is disabled for call as H245 address is " + "provided in Progress message (%s, %s)\n", + call->callType, call->callToken); + } + ret = ooH323GetIpPortFromH225TransportAddress(call, + &progress->h245Address, call->remoteIP, + &call->remoteH245Port); + if(ret != OO_OK) + { + OOTRACEERR3("Error: Unknown H245 address type in received " + "Progress message (%s, %s)", call->callType, + call->callToken); + /* Mark call for clearing */ + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + return OO_OK; } @@ -1056,6 +1320,9 @@ DListNode *pNode = NULL; OOTimer *pTimer=NULL; int type = q931Msg->messageType; + struct timespec ts; + int gkWaits; + ast_mutex_t gmutex; switch(type) { case Q931SetupMsg: /* SETUP message is received */ @@ -1065,14 +1332,14 @@ /* H225 message callback */ if(gH323ep.h225Callbacks.onReceivedSetup) - gH323ep.h225Callbacks.onReceivedSetup(call, q931Msg); + ret = gH323ep.h225Callbacks.onReceivedSetup(call, q931Msg); /* Free up the mem used by the received message, as it's processing is done. */ - ooFreeQ931Message(q931Msg); - - ooSendCallProceeding(call);/* Send call proceeding message*/ + if (ret == OO_OK) { + + ooFreeQ931Message(call->msgctxt, q931Msg); /* DISABLEGK is used to selectively disable gatekeeper use. For incoming calls DISABLEGK can be set in onReceivedSetup callback by @@ -1083,19 +1350,37 @@ { if(gH323ep.gkClient->state == GkClientRegistered) { + call->callState = OO_CALL_WAITING_ADMISSION; + // ast_mutex_lock(&call->Lock); ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE); - call->callState = OO_CALL_WAITING_ADMISSION; + ast_mutex_init(&gmutex); + for (gkWaits = 0; gkWaits < 1000; gkWaits++) { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec += 24000000; + ast_mutex_lock(&gmutex); + ast_cond_timedwait(&call->gkWait, &gmutex, &ts); + ast_mutex_unlock(&gmutex); + if (call->callState != OO_CALL_WAITING_ADMISSION) + break; + } + ast_mutex_destroy(&gmutex); + // ast_mutex_unlock(&call->Lock); + } - else{ + else { /* TODO: Should send Release complete with reject reason */ OOTRACEERR1("Error:Ignoring incoming call as not yet" "registered with Gk\n"); + call->callState = OO_CALL_CLEAR; } } - else { - ret = ooH323CallAdmitted (call); - } + if (call->callState < OO_CALL_CLEAR) { + ooSendCallProceeding(call);/* Send call proceeding message*/ + ret = ooH323CallAdmitted (call); + } + + } /* end ret == OO_OK */ break; @@ -1104,7 +1389,7 @@ call->callType, call->callToken); ooOnReceivedCallProceeding(call, q931Msg); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; @@ -1112,11 +1397,24 @@ OOTRACEINFO3("H.225 Alerting message received (%s, %s)\n", call->callType, call->callToken); + call->alertingTime = (H235TimeStamp) time(NULL); ooOnReceivedAlerting(call, q931Msg); if(gH323ep.h323Callbacks.onAlerting && call->callStatemsgctxt, q931Msg); + break; + + + case Q931ProgressMsg:/* PROGRESS message received */ + OOTRACEINFO3("H.225 Progress message received (%s, %s)\n", + call->callType, call->callToken); + + ooOnReceivedProgress(call, q931Msg); + + if(gH323ep.h323Callbacks.onProgress && call->callStatemsgctxt, q931Msg); break; @@ -1124,6 +1422,8 @@ OOTRACEINFO3("H.225 Connect message received (%s, %s)\n", call->callType, call->callToken); + call->connectTime = (H235TimeStamp) time(NULL); + /* Disable call establishment timer */ for(i = 0; itimerList.count; i++) { @@ -1151,12 +1451,18 @@ if(gH323ep.h323Callbacks.onCallEstablished) gH323ep.h323Callbacks.onCallEstablished(call); } - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); + + if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK)) { + if(gH323ep.gkClient->state == GkClientRegistered) { + ooGkClientSendIRR(gH323ep.gkClient, call); + } + } break; case Q931InformationMsg: OOTRACEINFO3("H.225 Information msg received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; @@ -1164,46 +1470,43 @@ OOTRACEINFO3("H.225 Release Complete message received (%s, %s)\n", call->callType, call->callToken); + call->endTime = (H235TimeStamp) time(NULL); + ooOnReceivedReleaseComplete(call, q931Msg); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; case Q931FacilityMsg: OOTRACEINFO3("H.225 Facility message Received (%s, %s)\n", call->callType, call->callToken); ooOnReceivedFacility(call, q931Msg); - ooFreeQ931Message(q931Msg); - break; - case Q931ProgressMsg: - OOTRACEINFO3("H.225 Progress message received (%s, %s)\n", - call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; case Q931StatusMsg: OOTRACEINFO3("H.225 Status message received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; case Q931StatusEnquiryMsg: OOTRACEINFO3("H.225 Status Inquiry message Received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; case Q931SetupAckMsg: OOTRACEINFO3("H.225 Setup Ack message received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; case Q931NotifyMsg: OOTRACEINFO3("H.225 Notify message Received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; default: OOTRACEWARN3("Invalid H.225 message type received (%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); } return ret; } @@ -1335,11 +1638,14 @@ } } else{ /* Empty facility message Check for tunneling */ + if (pH323UUPdu->h323_message_body.t == + T_H225H323_UU_PDU_h323_message_body_empty) { OOTRACEDBGB3("Handling tunneled messages in empty Facility message." " (%s, %s)\n", call->callType, call->callToken); ooHandleTunneledH245Messages(call, pH323UUPdu); OOTRACEDBGB3("Finished handling tunneled messages in empty Facility " "message. (%s, %s)\n", call->callType, call->callToken); + } } return OO_OK; @@ -1378,8 +1684,9 @@ ipAddress->ip.data[3]); call->remoteH245Port = ipAddress->port; - /* disable tunneling for this call */ + /* disable tunneling & faststart for this call */ OO_CLRFLAG (call->flags, OO_M_TUNNELING); + OO_CLRFLAG (call->flags, OO_M_FASTSTART); /*Establish an H.245 connection */ ret = ooCreateH245Connection(call); @@ -1396,7 +1703,7 @@ (OOH323CallData *call, H225H323_UU_PDU * pH323UUPdu) { H245Message *pmsg; - OOCTXT *pctxt = &gH323ep.msgctxt; + OOCTXT *pctxt = call->msgctxt; int ret=0,i=0; OOTRACEDBGC3("Checking for tunneled H.245 messages (%s, %s)\n", @@ -1608,6 +1915,54 @@ } +int ooPopulatePrefixList(OOCTXT *pctxt, OOAliases *pAliases, + H225_SeqOfH225SupportedPrefix *pPrefixList ) +{ + H225SupportedPrefix *pPrefixEntry=NULL; + OOAliases * pAlias=NULL; + ASN1BOOL bValid=FALSE; + int i = 0; + + dListInit(pPrefixList); + if(pAliases) + { + pAlias = pAliases; + while(pAlias) + { + pPrefixEntry = NULL; + switch(pAlias->type) + { + case T_H225AliasAddress_dialedDigits: + pPrefixEntry = (H225SupportedPrefix *)memAlloc(pctxt, + sizeof(H225SupportedPrefix)); + if(!pPrefixEntry) { + OOTRACEERR1("ERROR:Memory - ooPopulatePrefixList - pAliasEntry\n"); + return OO_FAILED; + } + pPrefixEntry->prefix.t = T_H225AliasAddress_dialedDigits; + pPrefixEntry->prefix.u.dialedDigits = (ASN1IA5String)memAlloc(pctxt, + strlen(pAlias->value)+1); + if(!pPrefixEntry->prefix.u.dialedDigits) { + OOTRACEERR1("ERROR:Memory - ooPopulatePrefixList - " + "dialedDigits\n"); + memFreePtr(pctxt, pPrefixEntry); + return OO_FAILED; + } + strcpy((char*)pPrefixEntry->prefix.u.dialedDigits, pAlias->value); + bValid = TRUE; + break; + default: + bValid = FALSE; + } + + if(bValid) + dListAppend( pctxt, pPrefixList, (void*)pPrefixEntry ); + + pAlias = pAlias->next; + } + } + return OO_OK; +} int ooPopulateAliasList(OOCTXT *pctxt, OOAliases *pAliases, H225_SeqOfH225AliasAddress *pAliasList ) { @@ -1622,6 +1977,10 @@ pAlias = pAliases; while(pAlias) { + if (pAlias->value[0] == 0) { + pAlias = pAlias->next; + continue; + } pAliasEntry = (H225AliasAddress*)memAlloc(pctxt, sizeof(H225AliasAddress)); if(!pAliasEntry) --- ./channels/ooh323c/src/ooports.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooports.c 2009-05-31 00:21:10.000000000 +0400 @@ -14,6 +14,8 @@ * *****************************************************************************/ +#include +#include #include "ooports.h" #include "ooh323ep.h" @@ -21,6 +23,7 @@ /** Global endpoint structure */ extern OOH323EndPoint gH323ep; +extern ast_mutex_t bindPortLock; /* Get the next port of type TCP/UDP/RTP */ int ooGetNextPort (OOH323PortType type) @@ -63,6 +66,8 @@ int initialPort, bindPort, ret; OOIPADDR ipAddrs; + ast_mutex_lock(&bindPortLock); + initialPort = ooGetNextPort (type); bindPort = initialPort; @@ -72,12 +77,13 @@ { if((ret=ooSocketBind(socket, ipAddrs, bindPort))==0) { + ast_mutex_unlock(&bindPortLock); return bindPort; } else { bindPort = ooGetNextPort (type); - if (bindPort == initialPort) return OO_FAILED; + if (bindPort == initialPort) { ast_mutex_unlock(&bindPortLock); return OO_FAILED; } } } } --- ./channels/ooh323c/src/ooh245.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh245.h 2009-07-28 22:49:05.000000000 +0400 @@ -69,7 +69,7 @@ * @return Completion status of operation: 0 (OO_OK) = success, * negative return value is error. */ -EXTERN int ooCreateH245Message(H245Message **msg, int type); +EXTERN int ooCreateH245Message(OOH323CallData* call, H245Message **msg, int type); /** * Frees up the memory used by the H245 message. @@ -288,7 +288,7 @@ * * @return OO_OK, on success. OO_FAILED, on failure. */ -EXTERN int ooCloseAllLogicalChannels(struct OOH323CallData *call); +EXTERN int ooCloseAllLogicalChannels(struct OOH323CallData *call, char* dir); /** --- ./channels/ooh323c/src/ooCalls.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCalls.h 2009-07-28 23:52:21.000000000 +0400 @@ -54,6 +54,10 @@ #define OO_M_DISABLEGK ASN1UINTCNT(0x01000000) #define OO_M_MANUALRINGBACK ASN1UINTCNT(0x10000000) +#define OO_M_TRYBEMASTER ASN1UINTCNT(0x00000010) +#define OO_M_AUDIOSESSION ASN1UINTCNT(0x00000100) +#define OO_M_DATASESSION ASN1UINTCNT(0x00000200) +#define OO_M_T38SUPPORTED ASN1UINTCNT(0x00000400) /** * Call states. @@ -67,7 +71,8 @@ OO_CALL_CLEAR, /*!< Call marked for clearing */ OO_CALL_CLEAR_RELEASERECVD, /*!< Release command received. */ OO_CALL_CLEAR_RELEASESENT, /*!< Release sent */ - OO_CALL_CLEARED /*!< Call cleared */ + OO_CALL_CLEARED, /*!< Call cleared */ + OO_CALL_REMOVED /* call removed */ } OOCallState; /** @@ -136,9 +141,18 @@ */ typedef struct OOH323CallData { OOCTXT *pctxt; + OOCTXT *msgctxt; + pthread_t callThread; + ast_cond_t gkWait; + ast_mutex_t Lock; + OOBOOL Monitor; + OOSOCKET CmdChan; + OOSOCKET cmdSock; + void* CmdChanLock; char callToken[20]; /* ex: ooh323c_call_1 */ char callType[10]; /* incoming/outgoing */ OOCallMode callMode; + int transfercap; ASN1USINT callReference; char ourCallerId[256]; H225CallIdentifier callIdentifier;/* The call identifier for the active @@ -149,6 +163,7 @@ ASN1UINT flags; OOCallState callState; OOCallClearReason callEndReason; + int q931cause; unsigned h245ConnectionAttempts; OOH245SessionState h245SessionState; int dtmfmode; @@ -165,7 +180,8 @@ char *remoteDisplayName; struct OOAliases *remoteAliases; struct OOAliases *ourAliases; /*aliases used in the call for us */ - OOMasterSlaveState masterSlaveState; /*!< Master-Slave state */ + OOMasterSlaveState masterSlaveState; /*!< Master-Slave state */ + OOMSAckStatus msAckStatus; /* Master-Slave ack's status */ ASN1UINT statusDeterminationNumber; OOCapExchangeState localTermCapState; OOCapExchangeState remoteTermCapState; @@ -185,6 +201,10 @@ unsigned nextSessionID; /* Note by default 1 is audio session, 2 is video and 3 is data, from 3 onwards master decides*/ DList timerList; ASN1UINT msdRetries; + ASN1UINT8 requestSequence; + ASN1UINT reqFlags; + ASN1UINT t38sides; + H235TimeStamp alertingTime, connectTime, endTime; /* time data for gatekeeper */ FastStartResponse *pFastStartRes; /* fast start response */ void *usrData; /*! +#include +#include + #include "ooq931.h" #include "ootrace.h" #include "ooasn1.h" @@ -33,6 +37,7 @@ /** Global endpoint structure */ extern OOH323EndPoint gH323ep; +extern ast_mutex_t newCallLock; static ASN1OBJID gProtocolID = { 6, { 0, 0, 8, 2250, 0, 4 } @@ -44,7 +49,8 @@ int offset, x; int rv = ASN_OK; char number[128]; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; dListInit (&msg->ies); /* clear information elements list */ @@ -229,7 +235,7 @@ we just ignore notify message as of now as handling is optional for end point*/ if(msg->messageType != Q931NotifyMsg) - rv = ooDecodeUUIE(msg); + rv = ooDecodeUUIE(pctxt, msg); return rv; } @@ -364,9 +370,9 @@ } } -int ooCreateQ931Message(Q931Message **q931msg, int msgType) +int ooCreateQ931Message(OOCTXT* pctxt, Q931Message **q931msg, int msgType) { - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ *q931msg = (Q931Message*)memAllocZ(pctxt, sizeof(Q931Message)); @@ -397,10 +403,12 @@ char aCallToken[200]; int ret = 0; + ast_mutex_lock(&newCallLock); sprintf (aCallToken, "ooh323c_%d", counter++); if (counter > OO_MAX_CALL_TOKEN) counter = 1; + ast_mutex_unlock(&newCallLock); if ((strlen(aCallToken)+1) < size) strcpy (callToken, aCallToken); @@ -479,24 +487,25 @@ } -int ooFreeQ931Message(Q931Message *q931Msg) +int ooFreeQ931Message(OOCTXT* pctxt, Q931Message *q931Msg) { if(!q931Msg) { - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(pctxt); } return OO_OK; } -int ooEncodeUUIE(Q931Message *q931msg) +int ooEncodeUUIE(OOCTXT* pctxt, Q931Message *q931msg) { ASN1OCTET msgbuf[1024]; ASN1OCTET * msgptr=NULL; int len; ASN1BOOL aligned = TRUE; Q931InformationElement* ie=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; - /* memset(msgbuf, 0, sizeof(msgbuf));*/ + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + memset(msgbuf, 0, sizeof(msgbuf)); if(!q931msg) { OOTRACEERR1("ERROR: Invalid Q931 message in add user-user IE\n"); @@ -547,14 +556,14 @@ return OO_OK; } -int ooDecodeUUIE(Q931Message *q931Msg) +int ooDecodeUUIE(OOCTXT* pctxt, Q931Message *q931Msg) { DListNode* curNode; unsigned int i; ASN1BOOL aligned=TRUE; int stat; Q931InformationElement *ie; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ if(q931Msg ==NULL) { OOTRACEERR1("Error: ooDecodeUUIE failed - NULL q931 message\n"); @@ -566,7 +575,7 @@ i++, curNode = curNode->next) { ie = (Q931InformationElement*) curNode->data; - if(ie->discriminator == Q931UserUserIE) + if(ie && ie->discriminator == Q931UserUserIE) break; } if(i == q931Msg->ies.count) @@ -602,7 +611,8 @@ (OOH323CallData* call, ASN1OCTET *msgbuf, ASN1UINT msglen) { - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; Q931Message q931Msg; int ret; @@ -650,7 +660,8 @@ else if(pq931Msg->messageType == Q931CallProceedingMsg){ msgbuf[i++] = OOCallProceeding; } - else if(pq931Msg->messageType == Q931AlertingMsg){ + else if(pq931Msg->messageType == Q931AlertingMsg || + pq931Msg->messageType == Q931ProgressMsg){ msgbuf[i++] = OOAlert; } else if(pq931Msg->messageType == Q931ReleaseCompleteMsg){ @@ -671,7 +682,7 @@ return OO_FAILED; } - stat = ooEncodeUUIE(pq931Msg); + stat = ooEncodeUUIE(call->msgctxt, pq931Msg); if(stat != OO_OK) { OOTRACEERR3("Error:Failed to encode uuie. (%s, %s)\n", call->callType, @@ -829,7 +840,8 @@ int ooSetFastStartResponse(OOH323CallData *pCall, Q931Message *pQ931msg, ASN1UINT *fsCount, ASN1DynOctStr **fsElem) { - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = pCall->msgctxt; int ret = 0, i=0, j=0, remoteMediaPort=0, remoteMediaControlPort = 0, dir=0; char remoteMediaIP[20], remoteMediaControlIP[20]; DListNode *pNode = NULL; @@ -874,7 +886,7 @@ /* If fast start supported and remote endpoint has sent faststart element */ - if(OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) && + if(OO_TESTFLAG(pCall->flags, OO_M_FASTSTART) && pCall->remoteFastStartOLCs.count>0) { pFS = (ASN1DynOctStr*)memAlloc(pctxt, @@ -1115,7 +1127,7 @@ { OOTRACEERR3("ERROR:Encoding of olc failed for faststart " "(%s, %s)\n", pCall->callType, pCall->callToken); - ooFreeQ931Message(pQ931msg); + ooFreeQ931Message(pctxt, pQ931msg); if(pCall->callState < OO_CALL_CLEAR) { pCall->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -1136,7 +1148,7 @@ { OOTRACEERR3("Error: Failed decoding FastStart Element (%s, %s)\n", pCall->callType, pCall->callToken); - ooFreeQ931Message(pQ931msg); + ooFreeQ931Message(pctxt, pQ931msg); if(pCall->callState < OO_CALL_CLEAR) { pCall->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -1201,11 +1213,12 @@ H225VendorIdentifier *vendor; H225CallProceeding_UUIE *callProceeding; Q931Message *q931msg=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; OOTRACEDBGC3("Building CallProceeding (%s, %s)\n", call->callType, call->callToken); - ret = ooCreateQ931Message(&q931msg, Q931CallProceedingMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931CallProceedingMsg); if(ret != OO_OK) { OOTRACEERR1("Error: In allocating memory for - H225 Call " @@ -1225,7 +1238,7 @@ memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation)); q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; q931msg->userInfo->h323_uu_pdu.h245Tunneling = - OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING); + OO_TESTFLAG(call->flags, OO_M_TUNNELING); q931msg->userInfo->h323_uu_pdu.h323_message_body.t = T_H225H323_UU_PDU_h323_message_body_callProceeding; @@ -1288,7 +1301,8 @@ OOTRACEERR3("Error:Failed to enqueue CallProceeding message to outbound queue.(%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return ret; } @@ -1299,9 +1313,10 @@ H225Alerting_UUIE *alerting; H225VendorIdentifier *vendor; Q931Message *q931msg=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; - ret = ooCreateQ931Message(&q931msg, Q931AlertingMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931AlertingMsg); if(ret != OO_OK) { OOTRACEERR1("Error: In allocating memory for - H225 " @@ -1309,6 +1324,8 @@ return OO_FAILED; } + call->alertingTime = (H235TimeStamp) time(NULL); + q931msg->callReference = call->callReference; q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt, @@ -1320,7 +1337,7 @@ } memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation)); q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; - q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags, + q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, OO_M_TUNNELING); q931msg->userInfo->h323_uu_pdu.h323_message_body.t = T_H225H323_UU_PDU_h323_message_body_alerting; @@ -1416,7 +1433,115 @@ OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); + + return ret; +} + +int ooSendProgress(OOH323CallData *call) +{ + int ret; + H225Progress_UUIE *progress; + H225VendorIdentifier *vendor; + Q931Message *q931msg=NULL; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; + + ret = ooCreateQ931Message(pctxt, &q931msg, Q931ProgressMsg); + if(ret != OO_OK) + { + OOTRACEERR1("Error: In allocating memory for - H225 " + "Alerting message\n"); + return OO_FAILED; + } + + q931msg->callReference = call->callReference; + + q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt, + sizeof(H225H323_UserInformation)); + if(!q931msg->userInfo) + { + OOTRACEERR1("ERROR:Memory - ooSendAlerting - userInfo\n"); + return OO_FAILED; + } + memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation)); + q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; + q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, + OO_M_TUNNELING); + q931msg->userInfo->h323_uu_pdu.h323_message_body.t = + T_H225H323_UU_PDU_h323_message_body_progress; + + progress = (H225Progress_UUIE*)memAlloc(pctxt, + sizeof(H225Progress_UUIE)); + if(!progress) + { + OOTRACEERR1("ERROR:Memory - ooSendProgress- alerting\n"); + return OO_FAILED; + } + memset(progress, 0, sizeof(H225Progress_UUIE)); + q931msg->userInfo->h323_uu_pdu.h323_message_body.u.progress = progress; + progress->m.multipleCallsPresent = 1; + progress->m.maintainConnectionPresent = 1; + progress->multipleCalls = FALSE; + progress->maintainConnection = FALSE; + + progress->callIdentifier.guid.numocts = + call->callIdentifier.guid.numocts; + memcpy(progress->callIdentifier.guid.data, + call->callIdentifier.guid.data, + call->callIdentifier.guid.numocts); + progress->protocolIdentifier = gProtocolID; + + /* Pose as Terminal or Gateway */ + if(gH323ep.isGateway) + progress->destinationInfo.m.gatewayPresent = TRUE; + else + progress->destinationInfo.m.terminalPresent = TRUE; + + progress->destinationInfo.m.vendorPresent = 1; + vendor = &progress->destinationInfo.vendor; + if(gH323ep.productID) + { + vendor->m.productIdPresent = 1; + vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID), + sizeof(vendor->productId.data)); + strncpy(vendor->productId.data, gH323ep.productID, + vendor->productId.numocts); + } + if(gH323ep.versionID) + { + vendor->m.versionIdPresent = 1; + vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID), + sizeof(vendor->versionId.data)); + strncpy(vendor->versionId.data, gH323ep.versionID, + vendor->versionId.numocts); + } + + vendor->vendor.t35CountryCode = gH323ep.t35CountryCode; + vendor->vendor.t35Extension = gH323ep.t35Extension; + vendor->vendor.manufacturerCode = gH323ep.manufacturerCode; + + ret = ooSetFastStartResponse(call, q931msg, + &progress->fastStart.n, &progress->fastStart.elem); + if(ret != ASN_OK) { return ret; } + if(progress->fastStart.n > 0) { + progress->m.fastStartPresent = TRUE; + } + else { + progress->m.fastStartPresent = FALSE; + } + + OOTRACEDBGA3("Built Alerting (%s, %s)\n", call->callType, call->callToken); + + ret = ooSendH225Msg(call, q931msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken); + } + + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return ret; } @@ -1427,11 +1552,12 @@ int ret=0; Q931Message *pQ931Msg = NULL; H225Facility_UUIE *facility=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; OOTRACEDBGA3("Building Facility message (%s, %s)\n", call->callType, call->callToken); - ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg); + ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg); if(ret != OO_OK) { OOTRACEERR3 @@ -1490,7 +1616,8 @@ ("Error:Failed to enqueue Facility message to outbound " "queue.(%s, %s)\n", call->callType, call->callToken); } - memReset (&gH323ep.msgctxt); + /* memReset (&gH323ep.msgctxt); */ + memReset (call->msgctxt); return ret; } @@ -1502,10 +1629,11 @@ enum Q931CauseValues cause = Q931ErrorInCauseIE; unsigned h225ReasonCode = T_H225ReleaseCompleteReason_undefinedReason; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; OOTRACEDBGA3("Building Release Complete message to send(%s, %s)\n", call->callType, call->callToken); - ret = ooCreateQ931Message(&q931msg, Q931ReleaseCompleteMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931ReleaseCompleteMsg); if(ret != OO_OK) { OOTRACEERR3("Error: In ooCreateQ931Message - H225 Release Complete " @@ -1539,7 +1667,7 @@ } memset(releaseComplete, 0, sizeof(H225ReleaseComplete_UUIE)); q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; - q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags, + q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, OO_M_TUNNELING); q931msg->userInfo->h323_uu_pdu.h323_message_body.t = T_H225H323_UU_PDU_h323_message_body_releaseComplete; @@ -1547,8 +1675,10 @@ /* Get cause value and h225 reason code corresponding to OOCallClearReason*/ ooQ931GetCauseAndReasonCodeFromCallClearReason(call->callEndReason, &cause, &h225ReasonCode); + if (call->q931cause == 0) + call->q931cause = cause; /* Set Cause IE */ - ooQ931SetCauseIE(q931msg, cause, 0, 0); + ooQ931SetCauseIE(pctxt, q931msg, call->q931cause, 0, 0); /* Set H225 releaseComplete reasonCode */ releaseComplete->m.reasonPresent = TRUE; @@ -1579,13 +1709,23 @@ OOTRACEERR3("Error:Failed to enqueue ReleaseComplete message to outbound" " queue.(%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return ret; } int ooSendConnect(OOH323CallData *call) { + + call->connectTime = (H235TimeStamp) time(NULL); + + if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK)) { + if(gH323ep.gkClient->state == GkClientRegistered) { + ooGkClientSendIRR(gH323ep.gkClient, call); + } + } + ooAcceptCall(call); return OO_OK; } @@ -1598,9 +1738,10 @@ H225TransportAddress_ipAddress *h245IpAddr; H225VendorIdentifier *vendor; Q931Message *q931msg=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; - ret = ooCreateQ931Message(&q931msg, Q931ConnectMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931ConnectMsg); if(ret != OO_OK) { OOTRACEERR1("Error: In allocating memory for - H225 " @@ -1610,11 +1751,11 @@ q931msg->callReference = call->callReference; /* Set bearer capability */ - if(OO_OK != ooSetBearerCapabilityIE(q931msg, Q931CCITTStd, - Q931TransferUnrestrictedDigital, Q931TransferPacketMode, - Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725)) - // Q931TransferSpeech, Q931TransferCircuitMode, - // Q931TransferRate64Kbps, Q931UserInfoLayer1G711ULaw)) + if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, + // Q931TransferUnrestrictedDigital, Q931TransferPacketMode, + // Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725)) + Q931TransferSpeech, Q931TransferCircuitMode, + Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw)) { OOTRACEERR3("Error: Failed to set bearer capability ie. (%s, %s)\n", call->callType, call->callToken); @@ -1765,10 +1906,12 @@ if(ret != OO_OK) { OOTRACEERR3("Error:Failed to enqueue Connect message to outbound queue.(%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt);*/ + memReset(call->msgctxt); return OO_FAILED; } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); #if 0 if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) @@ -1798,6 +1941,8 @@ OOH323CallData *fwdedCall=NULL; OOCTXT *pctxt; ooAliases *pNewAlias=NULL, *alias=NULL; + struct timespec ts; + ast_mutex_t gmutex; int i=0, irand=0, ret = OO_OK; /* Note: We keep same callToken, for new call which is going to replace an existing call, thus treating it as a single call.*/ @@ -1852,15 +1997,46 @@ MakeCall command */ ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, fwdedCall, FALSE); fwdedCall->callState = OO_CALL_WAITING_ADMISSION; + ast_mutex_lock(&fwdedCall->Lock); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 24; + ast_mutex_init(&gmutex); + ast_mutex_lock(&gmutex); + ast_cond_timedwait(&fwdedCall->gkWait, &gmutex, &ts); + ast_mutex_unlock(&gmutex); + ast_mutex_destroy(&gmutex); + if (fwdedCall->callState == OO_CALL_WAITING_ADMISSION) /* GK is not responding */ + fwdedCall->callState = OO_CALL_CLEAR; + ast_mutex_unlock(&fwdedCall->Lock); + } - else { + if (fwdedCall->callState < OO_CALL_CLEAR) { + ast_mutex_lock(&fwdedCall->Lock); ret = ooH323CallAdmitted (fwdedCall); + ast_mutex_unlock(&fwdedCall->Lock); } return OO_OK; } +int ooH323NewCall(char *callToken) { + OOH323CallData* call; + if(!callToken) + { + OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n"); + return OO_FAILED; + } + call = ooCreateCall("outgoing", callToken); + if (!call) + { + OOTRACEERR1("ERROR: Can't create call %s\n"); + return OO_FAILED; + } + + return OO_OK; +} + int ooH323MakeCall(char *dest, char *callToken, ooCallOptions *opts) { OOCTXT *pctxt; @@ -1868,6 +2044,9 @@ int ret=0, i=0, irand=0; char tmp[30]="\0"; char *ip=NULL, *port = NULL; + struct timespec ts; + int gkWaits; + ast_mutex_t gmutex; if(!dest) { @@ -1880,7 +2059,14 @@ return OO_FAILED; } - call = ooCreateCall("outgoing", callToken); + /* call = ooCreateCall("outgoing", callToken); */ + call = ooFindCallByToken(callToken); + if (!call) + { + OOTRACEERR1("ERROR: Can't create call %s\n"); + return OO_FAILED; + } + pctxt = call->pctxt; if(opts) { @@ -1900,10 +2086,11 @@ OO_CLRFLAG(call->flags, OO_M_DISABLEGK); call->callMode = opts->callMode; + call->transfercap = opts->transfercap; } - ret = ooParseDestination(call, dest, tmp, 30, &call->remoteAliases); + ret = ooParseDestination(call, dest, tmp, 24, &call->remoteAliases); if(ret != OO_OK) { OOTRACEERR2("Error: Failed to parse the destination string %s for " @@ -1936,14 +2123,34 @@ { /* No need to check registration status here as it is already checked for MakeCall command */ - ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE); - call->callState = OO_CALL_WAITING_ADMISSION; - } - else { - /* Send as H225 message to calling endpoint */ - ret = ooH323CallAdmitted (call); + + call->callState = OO_CALL_WAITING_ADMISSION; + // ast_mutex_lock(&call->Lock); + ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE); + ast_mutex_init(&gmutex); + for (gkWaits = 0; gkWaits < 1000; gkWaits++) { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec += 24000000; + ast_mutex_lock(&gmutex); + ast_cond_timedwait(&call->gkWait, &gmutex, &ts); + ast_mutex_unlock(&gmutex); + if (call->callState != OO_CALL_WAITING_ADMISSION) + break; + } + ast_mutex_destroy(&gmutex); + // ast_mutex_unlock(&call->Lock); + } + /* Send as H225 message to calling endpoint */ + ast_mutex_lock(&call->Lock); + if (call->callState < OO_CALL_CLEAR) + if ((ret = ooH323CallAdmitted (call)) != OO_OK) { + ast_mutex_unlock(&call->Lock); + return ret; + } + ast_mutex_unlock(&call->Lock); + return OO_OK; } @@ -1972,6 +2179,11 @@ } return OO_FAILED; } + + if(gH323ep.h323Callbacks.onOutgoingCall) { + /* Outgoing call callback function */ + gH323ep.h323Callbacks.onOutgoingCall(call); + } ret = ooH323MakeCall_helper(call); } @@ -2012,9 +2224,10 @@ ASN1BOOL aligned = 1; ooAliases *pAlias = NULL; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; - ret = ooCreateQ931Message(&q931msg, Q931SetupMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931SetupMsg); if(ret != OO_OK) { OOTRACEERR1("ERROR:Failed to Create Q931 SETUP Message\n "); @@ -2024,10 +2237,11 @@ q931msg->callReference = call->callReference; /* Set bearer capability */ - if(OO_OK != ooSetBearerCapabilityIE(q931msg, Q931CCITTStd, - Q931TransferUnrestrictedDigital, Q931TransferPacketMode, - Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725)) -// Q931TransferRate64Kbps, Q931UserInfoLayer1G711ULaw)) + if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, + // Q931TransferUnrestrictedDigital, Q931TransferPacketMode, + call->transfercap, Q931TransferCircuitMode, + // Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725)) + Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw)) { OOTRACEERR3("Error: Failed to set bearer capability ie.(%s, %s)\n", call->callType, call->callToken); @@ -2035,14 +2249,14 @@ } /* Set calling party number Q931 IE */ - if(call->callingPartyNumber) - ooQ931SetCallingPartyNumberIE(q931msg, + if(call->callingPartyNumber && call->callingPartyNumber[0]) + ooQ931SetCallingPartyNumberIE(pctxt, q931msg, (const char*)call->callingPartyNumber, 1, 0, 0, 0); /* Set called party number Q931 IE */ if(call->calledPartyNumber) - ooQ931SetCalledPartyNumberIE(q931msg, + ooQ931SetCalledPartyNumberIE(pctxt, q931msg, (const char*)call->calledPartyNumber, 1, 0); else if(call->remoteAliases) { pAlias = call->remoteAliases; @@ -2063,7 +2277,7 @@ return OO_FAILED; } strcpy(call->calledPartyNumber, pAlias->value); - ooQ931SetCalledPartyNumberIE(q931msg, + ooQ931SetCalledPartyNumberIE(pctxt, q931msg, (const char*)call->calledPartyNumber, 1, 0); } @@ -2208,7 +2422,7 @@ setup->sourceCallSignalAddress.u.ipAddress = srcCallSignalIpAddress; setup->m.sourceCallSignalAddressPresent=TRUE; /* No fast start */ - if(!OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART)) + if(!OO_TESTFLAG(call->flags, OO_M_FASTSTART)) { setup->m.fastStartPresent = FALSE; } @@ -2257,7 +2471,10 @@ continue; } +/* don't send t38/other data caps in fasstart olcs */ + if (epCap->capType == OO_CAP_TYPE_DATA) + continue; OOTRACEDBGC4("Building olcs with capability %s. (%s, %s)\n", ooGetCapTypeText(epCap->cap), call->callType, @@ -2270,7 +2487,7 @@ { OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)" "\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2290,7 +2507,7 @@ { OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)" "\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2311,7 +2528,7 @@ { OOTRACEERR3("Error: Failed decoding FastStart Element." "(%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2338,7 +2555,7 @@ { OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)" "\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2358,7 +2575,7 @@ { OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)" "\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2378,7 +2595,7 @@ { OOTRACEERR3("Error: Failed decoding FastStart Element." "(%s, %s)\n", call->callType, call->callToken); - ooFreeQ931Message(q931msg); + ooFreeQ931Message(pctxt, q931msg); if(call->callState < OO_CALL_CLEAR) { call->callEndReason = OO_REASON_LOCAL_CLEARED; @@ -2442,8 +2659,10 @@ /* For H.323 version 4 and higher, if fast connect, tunneling should be supported. */ - if(OO_TESTFLAG(call->flags, OO_M_FASTSTART)) + if(OO_TESTFLAG(call->flags, OO_M_FASTSTART)) { q931msg->userInfo->h323_uu_pdu.h245Tunneling = TRUE; + OO_SETFLAG(call->flags, OO_M_TUNNELING); + } OOTRACEDBGA3("Built SETUP message (%s, %s)\n", call->callType, call->callToken); @@ -2457,7 +2676,8 @@ { OOTRACEERR3("Error:Failed to enqueue SETUP message to outbound queue. (%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt);*/ + memReset(call->msgctxt); return ret; } @@ -2469,9 +2689,10 @@ int ret; H225Information_UUIE *information=NULL; Q931Message *q931msg=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; - ret = ooCreateQ931Message(&q931msg, Q931InformationMsg); + ret = ooCreateQ931Message(pctxt, &q931msg, Q931InformationMsg); if(ret != OO_OK) { OOTRACEERR3("Error: In allocating memory for - H225 Information message." @@ -2487,11 +2708,12 @@ { OOTRACEERR3("ERROR:Memory - ooQ931SendDTMFAsKeypadIE - userInfo" "(%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return OO_FAILED; } q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; - q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags, + q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, OO_M_TUNNELING); q931msg->userInfo->h323_uu_pdu.h323_message_body.t = T_H225H323_UU_PDU_h323_message_body_information; @@ -2502,7 +2724,8 @@ { OOTRACEERR3("ERROR:Memory - ooQ931SendDTMFAsKeypadIE - information" "(%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return OO_FAILED; } q931msg->userInfo->h323_uu_pdu.h323_message_body.u.information = @@ -2516,12 +2739,13 @@ information->protocolIdentifier = gProtocolID; /*Add keypad IE*/ - ret = ooQ931SetKeypadIE(q931msg, data); + ret = ooQ931SetKeypadIE(pctxt, q931msg, data); if(ret != OO_OK) { OOTRACEERR3("Error:Creating keypad IE for (%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return OO_FAILED; } @@ -2531,7 +2755,8 @@ OOTRACEERR3("Error:Failed to enqueue Information message to outbound " "queue. (%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return ret; @@ -2586,7 +2811,7 @@ strcpy(call->pCallFwdData->ip, ip); } - ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg); + ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg); if(ret != OO_OK) { OOTRACEERR3 @@ -2683,7 +2908,7 @@ return ret; } -int ooH323HangCall(char * callToken, OOCallClearReason reason) +int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931cause) { OOH323CallData *call; @@ -2698,19 +2923,20 @@ if(call->callState < OO_CALL_CLEAR) { call->callEndReason = reason; + call->q931cause = q931cause; call->callState = OO_CALL_CLEAR; } return OO_OK; } int ooSetBearerCapabilityIE - (Q931Message *pmsg, enum Q931CodingStandard codingStandard, + (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CodingStandard codingStandard, enum Q931InformationTransferCapability capability, enum Q931TransferMode transferMode, enum Q931TransferRate transferRate, enum Q931UserInfoLayer1Protocol userInfoLayer1) { unsigned size = 3; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ if(pmsg->bearerCapabilityIE) { @@ -2738,10 +2964,10 @@ return OO_OK; } -int ooQ931SetKeypadIE(Q931Message *pmsg, const char* data) +int ooQ931SetKeypadIE(OOCTXT* pctxt, Q931Message *pmsg, const char* data) { unsigned len = 0; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ len = strlen(data); pmsg->keypadIE = (Q931InformationElement*) @@ -2758,15 +2984,12 @@ return OO_OK; } - - - int ooQ931SetCallingPartyNumberIE - (Q931Message *pmsg, const char *number, unsigned plan, unsigned type, + (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type, unsigned presentation, unsigned screening) { unsigned len = 0; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ if(pmsg->callingPartyNumberIE) { @@ -2793,10 +3016,10 @@ } int ooQ931SetCalledPartyNumberIE - (Q931Message *pmsg, const char *number, unsigned plan, unsigned type) + (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type) { unsigned len = 0; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ if(pmsg->calledPartyNumberIE) { @@ -2822,10 +3045,10 @@ } int ooQ931SetCauseIE - (Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding, + (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding, unsigned location) { - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ if(pmsg->causeIE){ memFreePtr(pctxt, pmsg->causeIE); @@ -2859,12 +3082,13 @@ ASN1DynOctStr * elem; int ret =0; H225Facility_UUIE *facility=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; OOTRACEDBGA4("Building Facility message for tunneling %s (%s, %s)\n", ooGetMsgTypeText(h245MsgType), call->callType, call->callToken); - ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg); + ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg); if(ret != OO_OK) { OOTRACEERR3("ERROR: In allocating memory for facility message " @@ -2880,7 +3104,8 @@ { OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - userInfo" " (%s, %s)\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt);*/ + memReset(call->msgctxt); return OO_FAILED; } memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation)); @@ -2899,7 +3124,8 @@ { OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - facility (%s, %s)" "\n", call->callType, call->callToken); - memReset(&gH323ep.msgctxt); + /* memReset(&gH323ep.msgctxt); */ + memReset(call->msgctxt); return OO_FAILED; } @@ -2951,7 +3177,8 @@ main received H225 message processing is finished. Rule. No reset when tunneling */ - memFreePtr(&gH323ep.msgctxt, pQ931Msg); + /* memFreePtr(&gH323ep.msgctxt, pQ931Msg); */ + memFreePtr(call->msgctxt, pQ931Msg); return ret; } @@ -3378,7 +3605,11 @@ "OORequestChannelCloseAck", "OORequestChannelCloseReject", "OORequestChannelCloseRelease", - "OOEndSessionCommand" + "OOEndSessionCommand", + "OOUserInputIndication", + "OORequestModeAck", + "OORequestModeReject", + "OORequestMode" }; int idx = msgType - OO_MSGTYPE_MIN; return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText)); --- ./channels/ooh323c/src/decode.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/decode.c 2009-05-31 00:15:23.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ooasn1.h" static int decode16BitConstrainedString --- ./channels/ooh323c/src/ooSocket.c 2008-07-30 07:07:14.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooSocket.c 2009-07-02 11:16:44.000000000 +0400 @@ -13,6 +13,9 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include +#include #include "ooSocket.h" #include "ootrace.h" @@ -303,7 +306,7 @@ if(ret != 0) return ASN_E_INVSOCKET; - host = inet_ntoa(addr.sin_addr); + host = ast_inet_ntoa(addr.sin_addr); if(host && strlen(host) < (unsigned)len) strcpy(ip, host); @@ -338,7 +341,7 @@ if (pNewSocket == 0) return ASN_E_INVPARAM; *pNewSocket = accept (socket, (struct sockaddr *) (void*) &m_addr, - (socklen_t *) &addr_length); + &addr_length); if (*pNewSocket <= 0) return ASN_E_INVSOCKET; if (destAddr != 0) @@ -444,7 +447,7 @@ *remoteport = ntohs(m_addr.sin_port); if(remotehost) { - host = inet_ntoa(m_addr.sin_addr); + host = ast_inet_ntoa(m_addr.sin_addr); if(strlen(host) < (hostBufLen-1)) strcpy(remotehost, host); else @@ -466,24 +469,54 @@ return ret; } +int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout) +{ + return poll(pfds, nfds, timeout); +} + +int ooPDRead(struct pollfd *pfds, int nfds, int fd) +{ + int i; + for (i=0;ih_addr_list[0], sizeof(struct in_addr)); - strcpy(pIPAddrs, inet_ntoa(addr)); - + memcpy(&addr, &phost.h_addr_list[0], sizeof(struct in_addr)); + strcpy(pIPAddrs, (ast_inet_ntoa(addr) == NULL) ? "127.0.0.1" : ast_inet_ntoa(addr)); + } else { + return -1; + } } else{ return -1; @@ -608,10 +641,7 @@ int flags; for (ifName = ifc.ifc_req; (void*)ifName < ifEndList; ifName++) { char *pName=NULL; - char addr[50]; -#ifdef ifr_netmask - char mask[50]; -#endif + char addr[50], mask[50]; pIf = (struct OOInterface*)memAlloc(pctxt, sizeof(struct OOInterface)); pName = (char*)memAlloc(pctxt, strlen(ifName->ifr_name)+1); @@ -653,7 +683,7 @@ memFreePtr(pctxt, pIf); continue; } - strcpy(addr, inet_ntoa(((struct sockaddr_in*)&ifReq.ifr_addr)->sin_addr)); + strcpy(addr, ast_inet_ntoa(((struct sockaddr_in*)&ifReq.ifr_addr)->sin_addr)); OOTRACEDBGA2("\tIP address is %s\n", addr); pIf->addr = (char*)memAlloc(pctxt, strlen(addr)+1); if(!pIf->addr) @@ -676,7 +706,7 @@ memFreePtr(pctxt, pIf); continue; } - strcpy(mask, inet_ntoa(((struct sockaddr_in *)&ifReq.ifr_netmask)->sin_addr)); + strcpy(mask, ast_inet_ntoa(((struct sockaddr_in *)&ifReq.ifr_netmask)->sin_addr)); OOTRACEDBGA2("\tMask is %s\n", mask); pIf->mask = (char*)memAlloc(pctxt, strlen(mask)+1); if(!pIf->mask) --- ./channels/ooh323c/src/ootypes.h 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ootypes.h 2009-07-28 22:49:05.000000000 +0400 @@ -61,7 +61,7 @@ -#define OOH323C_VERSION "v0.8.3" +#define OOH323C_VERSION "v0.8.3m" #ifndef EXTERN #ifdef MAKE_DLL @@ -92,6 +92,11 @@ OO_MasterSlave_Slave } OOMasterSlaveState; +typedef enum OOMSAckStatus { + OO_msAck_localSent, + OO_msAck_remoteReceived +} OOMSAckStatus; + /** * States defined for the capability exchange procedure. */ @@ -180,8 +185,11 @@ #define OORequestChannelCloseRelease 128 #define OOEndSessionCommand 129 #define OOUserInputIndication 130 +#define OORequestModeAck 131 +#define OORequestModeReject 132 +#define OORequestMode 133 -#define OO_MSGTYPE_MAX 130 +#define OO_MSGTYPE_MAX 133 /* Timer types */ #define OO_CALLESTB_TIMER (1<<0) @@ -238,6 +246,7 @@ OOBOOL tunneling; /*!< Use H.245 tunneling */ OOBOOL disableGk; /*!< Disable use of gatekeeper */ OOCallMode callMode; /*!< Type of channel to setup with FastStart */ + int transfercap; /* q931 cap */ }ooCallOptions; --- ./channels/ooh323c/src/dlist.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/dlist.c 2009-05-31 00:15:34.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ooasn1.h" void dListInit (DList* pList) --- ./channels/ooh323c/src/ooGkClient.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooGkClient.h 2009-07-03 23:50:45.000000000 +0400 @@ -47,7 +47,7 @@ -#define MAX_IP_LEN 15 +#define MAX_IP_LEN 18 #define DEFAULT_GKPORT 1719 #define MULTICAST_GKADDRESS "224.0.1.41" #define MULTICAST_GKPORT 1718 @@ -204,6 +204,7 @@ ASN1UINT arqTimeout; ASN1UINT drqTimeout; enum OOGkClientState state; + ast_mutex_t Lock; } ooGkClient; struct OOAliases; --- ./channels/ooh323c/src/ooCmdChannel.c 2008-12-22 20:01:00.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCmdChannel.c 2009-07-28 22:49:05.000000000 +0400 @@ -14,6 +14,8 @@ * *****************************************************************************/ +#include +#include #include "ooStackCmds.h" #include "ootrace.h" #include "ooq931.h" @@ -23,11 +25,12 @@ #include "ooCalls.h" #include "ooCmdChannel.h" + /** Global endpoint structure */ extern OOH323EndPoint gH323ep; OOSOCKET gCmdChan = 0; -pthread_mutex_t gCmdChanLock; +ast_mutex_t gCmdChanLock; int ooCreateCmdConnection() { @@ -37,7 +40,7 @@ if ((ret = pipe(thePipe)) == -1) { return OO_FAILED; } - pthread_mutex_init(&gCmdChanLock, NULL); + ast_mutex_init(&gCmdChanLock); gH323ep.cmdSock = dup(thePipe[0]); close(thePipe[0]); @@ -46,6 +49,30 @@ return OO_OK; } +int ooCreateCallCmdConnection(OOH323CallData* call) +{ + int ret = 0; + int thePipe[2]; + + OOTRACEINFO2("INFO: create cmd connect for call: %lx\n", call); + + call->CmdChanLock = malloc(sizeof(ast_mutex_t)); + ast_mutex_init((ast_mutex_t *)call->CmdChanLock); + + + if ((ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, thePipe)) == -1) { + ast_mutex_destroy((ast_mutex_t *)call->CmdChanLock); + free(call->CmdChanLock); + call->CmdChanLock = NULL; + return OO_FAILED; + } + ast_mutex_lock((ast_mutex_t *)call->CmdChanLock); + call->cmdSock = thePipe[0]; + call->CmdChan = thePipe[1]; + ast_mutex_unlock((ast_mutex_t *)call->CmdChanLock); + return OO_OK; +} + int ooCloseCmdConnection() { @@ -53,7 +80,21 @@ gH323ep.cmdSock = 0; close(gCmdChan); gCmdChan = 0; - pthread_mutex_destroy(&gCmdChanLock); + ast_mutex_destroy(&gCmdChanLock); + + return OO_OK; +} +int ooCloseCallCmdConnection(OOH323CallData* call) +{ + ast_mutex_lock(call->CmdChanLock); + close(call->cmdSock); + call->cmdSock = 0; + close(call->CmdChan); + call->CmdChan = 0; + ast_mutex_unlock(call->CmdChanLock); + ast_mutex_destroy((ast_mutex_t *)call->CmdChanLock); + free(call->CmdChanLock); + call->CmdChanLock = NULL; return OO_OK; } @@ -61,12 +102,47 @@ int ooWriteStackCommand(OOStackCommand *cmd) { - pthread_mutex_lock(&gCmdChanLock); + ast_mutex_lock(&gCmdChanLock); if (write(gCmdChan, (char*)cmd, sizeof(OOStackCommand)) == -1) { - pthread_mutex_unlock(&gCmdChanLock); + ast_mutex_unlock(&gCmdChanLock); return OO_FAILED; } - pthread_mutex_unlock(&gCmdChanLock); + ast_mutex_unlock(&gCmdChanLock); + + return OO_OK; +} +int ooWriteCallStackCommand(OOH323CallData* call, OOStackCommand *cmd) +{ + unsigned char buffer[MAXMSGLEN]; + unsigned char* bPoint; + + memcpy(buffer, cmd, sizeof(OOStackCommand)); + bPoint = buffer + sizeof(OOStackCommand); + if (cmd->param1 && cmd->plen1 > 0) { + if (bPoint + cmd->plen1 >= buffer + MAXMSGLEN) + return OO_FAILED; + memcpy(bPoint, cmd->param1, cmd->plen1); + bPoint += cmd->plen1; + } + if (cmd->param2 && cmd->plen2 > 0) { + if (bPoint + cmd->plen2 >= buffer + MAXMSGLEN) + return OO_FAILED; + memcpy(bPoint, cmd->param2, cmd->plen2); + bPoint += cmd->plen2; + } + if (cmd->param3 && cmd->plen3 > 0) { + if (bPoint + cmd->plen3 >= buffer + MAXMSGLEN) + return OO_FAILED; + memcpy(bPoint, cmd->param3, cmd->plen3); + bPoint += cmd->plen3; + } + + ast_mutex_lock((ast_mutex_t *)call->CmdChanLock); + if (write(call->CmdChan, buffer, bPoint - buffer) == -1) { + ast_mutex_unlock((ast_mutex_t *)call->CmdChanLock); + return OO_FAILED; + } + ast_mutex_unlock((ast_mutex_t *)call->CmdChanLock); return OO_OK; } @@ -79,7 +155,9 @@ int i, recvLen = 0; OOStackCommand cmd; memset(&cmd, 0, sizeof(OOStackCommand)); + ast_mutex_lock(&gCmdChanLock); recvLen = read(gH323ep.cmdSock, buffer, MAXMSGLEN); + ast_mutex_unlock(&gCmdChanLock); if(recvLen <= 0) { OOTRACEERR1("Error:Failed to read CMD message\n"); @@ -104,8 +182,19 @@ OOTRACEINFO2("Processing MakeCall command %s\n", (char*)cmd.param2); - ooH323MakeCall ((char*)cmd.param1, (char*)cmd.param2, - (ooCallOptions*)cmd.param3); + ooH323NewCall ((char*)cmd.param2); + break; + + case OO_CMD_MANUALPROGRESS: + pCall = ooFindCallByToken((char*)cmd.param1); + if(!pCall) { + OOTRACEINFO2("Call \"%s\" does not exist\n", + (char*)cmd.param1); + OOTRACEINFO1("Call migth be cleared/closed\n"); + } + else { + ooSendProgress(ooFindCallByToken((char*)cmd.param1)); + } break; case OO_CMD_MANUALRINGBACK: @@ -147,10 +236,10 @@ break; case OO_CMD_HANGCALL: - OOTRACEINFO2("Processing Hang call command %s\n", - (char*)cmd.param1); + OOTRACEINFO3("Processing Hang call command %s with q931 cause %d\n", + (char*)cmd.param1, *(int *) cmd.param3); ooH323HangCall((char*)cmd.param1, - *(OOCallClearReason*)cmd.param2); + *(OOCallClearReason*)cmd.param2, *(int *) cmd.param3); break; case OO_CMD_SENDDIGIT: @@ -190,4 +279,139 @@ return OO_OK; } +int ooReadAndProcessCallStackCommand(OOH323CallData* call) +{ + OOH323CallData *pCall = NULL; + unsigned char buffer[MAXMSGLEN]; + unsigned char *bPoint; + int i, recvLen = 0; + OOStackCommand cmd; + memset(&cmd, 0, sizeof(OOStackCommand)); + if (call->CmdChanLock) { + ast_mutex_lock((ast_mutex_t *)call->CmdChanLock); + recvLen = read(call->cmdSock, buffer, MAXMSGLEN); + ast_mutex_unlock((ast_mutex_t *)call->CmdChanLock); + } else { + recvLen = read(call->cmdSock, buffer, MAXMSGLEN); + } + if(recvLen <= 0) + { + OOTRACEERR1("Error:Failed to read CMD message\n"); + return OO_FAILED; + } + + bPoint = buffer; + while (bPoint < buffer + recvLen - sizeof(OOStackCommand)) { + + memcpy(&cmd, bPoint, sizeof(OOStackCommand)); + bPoint += sizeof(OOStackCommand); + + if (cmd.plen1 > 0) { + cmd.param1 = malloc(cmd.plen1 + 1); + if (!cmd.param1) + return OO_FAILED; + memset(cmd.param1, 0, cmd.plen1 + 1); + memcpy(cmd.param1, bPoint, cmd.plen1); + bPoint += cmd.plen1; + } + + if (cmd.plen2 > 0) { + cmd.param2 = malloc(cmd.plen2 + 1); + if (!cmd.param2) + return OO_FAILED; + memset(cmd.param2, 0, cmd.plen2 + 1); + memcpy(cmd.param2, bPoint, cmd.plen2); + bPoint += cmd.plen2; + } + + if (cmd.plen3 > 0) { + cmd.param3 = malloc(cmd.plen3 + 1); + if (!cmd.param3) + return OO_FAILED; + memset(cmd.param3, 0, cmd.plen3 + 1); + memcpy(cmd.param3, bPoint, cmd.plen3); + bPoint += cmd.plen3; + } + + if(cmd.type == OO_CMD_NOOP) + continue; + + if(gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered) + { + OOTRACEINFO1("Ignoring stack command as Gk Client is not registered" + " yet\n"); + } + else { + switch(cmd.type) { + case OO_CMD_MAKECALL: + OOTRACEINFO2("Processing MakeCall command %s\n", + (char*)cmd.param2); + + ooH323MakeCall ((char*)cmd.param1, (char*)cmd.param2, + (ooCallOptions*)cmd.param3); + break; + + case OO_CMD_MANUALPROGRESS: + ooSendProgress(call); + break; + + case OO_CMD_MANUALRINGBACK: + if(OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK)) + { + ooSendAlerting(call); + if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) { + ooSendConnect(call); + } + } + break; + + case OO_CMD_ANSCALL: + ooSendConnect(call); + break; + + case OO_CMD_FWDCALL: + OOTRACEINFO3("Forwarding call %s to %s\n", (char*)cmd.param1, + (char*)cmd.param2); + ooH323ForwardCall((char*)cmd.param1, (char*)cmd.param2); + break; + + case OO_CMD_HANGCALL: + OOTRACEINFO2("Processing Hang call command %s with q931 cause %d\n", + (char*)cmd.param1); + ooH323HangCall((char*)cmd.param1, + *(OOCallClearReason*)cmd.param2, *(int *) cmd.param3); + break; + + case OO_CMD_SENDDIGIT: + if(call->jointDtmfMode & OO_CAP_DTMF_H245_alphanumeric) { + ooSendH245UserInputIndication_alphanumeric( + call, (const char*)cmd.param2); + } + else if(call->jointDtmfMode & OO_CAP_DTMF_H245_signal) { + ooSendH245UserInputIndication_signal( + call, (const char*)cmd.param2); + } + else { + ooQ931SendDTMFAsKeyPadIE(call, (const char*)cmd.param2); + } + + break; + + case OO_CMD_REQMODE: + OOTRACEINFO3("Processing RequestMode command %s, requested mode is %d\n", + (char *)cmd.param1, *(int *)cmd.param2); + ooSendRequestMode(call, *(int *)cmd.param2); + break; + + default: OOTRACEERR1("ERROR:Unknown command\n"); + } + } + if(cmd.param1) free(cmd.param1); + if(cmd.param2) free(cmd.param2); + if(cmd.param3) free(cmd.param3); + } + + + return OO_OK; +} --- ./channels/ooh323c/src/ooTimer.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooTimer.c 2009-05-31 00:23:35.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ooDateTime.h" #include "ooTimer.h" #include "ootrace.h" --- ./channels/ooh323c/src/ooLogChan.c 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooLogChan.c 2009-07-28 22:49:05.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ooCalls.h" #include "ooh323ep.h" @@ -187,7 +190,7 @@ { OOTRACEDBGC3("ooFindLogicalChannel, checking channel: %d:%s\n", pChannel->sessionID, pChannel->dir); - if(pChannel->sessionID == sessionID) + if(pChannel->sessionID == sessionID || pChannel->sessionID == 0) { if(!strcmp(pChannel->dir, dir)) { @@ -230,6 +233,26 @@ return NULL; } +/* function is to get channel with particular direction */ + +OOLogicalChannel* ooGetTransmitLogicalChannel + (OOH323CallData *call) +{ + OOLogicalChannel * pChannel = NULL; + pChannel = call->logicalChans; + while(pChannel) + { + OOTRACEINFO6("Listing logical channel %d cap %d state %d for (%s, %s)\n", + pChannel->channelNo, pChannel->chanCap->cap, pChannel->state, + call->callType, call->callToken); + if(!strcmp(pChannel->dir, "transmit") && pChannel->state == OO_LOGICALCHAN_IDLE) + return pChannel; + else + pChannel = pChannel->next; + } + return NULL; +} + int ooClearAllLogicalChannels(OOH323CallData *call) { OOLogicalChannel * temp = NULL, *prev = NULL; --- ./channels/ooh323c/src/printHandler.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/printHandler.c 2009-05-31 00:23:04.000000000 +0400 @@ -17,10 +17,13 @@ the fields of an encoded PER message to stdout in a structured output format.. */ +#include +#include + #include -#ifdef HAVE_MALLOC_H +/* #ifdef HAVE_MALLOC_H #include -#endif +#endif */ #include "printHandler.h" #include "ootypes.h" #include "rtctype.h" --- ./channels/ooh323c/src/encode.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/encode.c 2009-05-31 00:18:38.000000000 +0400 @@ -14,7 +14,10 @@ * *****************************************************************************/ +#include +#include #include + #include "ooasn1.h" static int encode16BitConstrainedString --- ./channels/ooh323c/src/context.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/context.c 2009-05-31 00:15:12.000000000 +0400 @@ -13,9 +13,12 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include #include "ooasn1.h" #include +#include int initContext (OOCTXT* pctxt) { @@ -25,6 +28,9 @@ pctxt->pMsgMemHeap = pctxt->pTypeMemHeap; memHeapAddRef (&pctxt->pMsgMemHeap); + + ast_mutex_init(&pctxt->pLock); + return ASN_OK; } @@ -55,6 +61,8 @@ int initSubContext (OOCTXT* pctxt, OOCTXT* psrc) { + /* ast_mutex_lock(&pctxt->pLock); */ + ast_mutex_lock(&psrc->pLock); int stat = ASN_OK; memset (pctxt, 0, sizeof(OOCTXT)); pctxt->pTypeMemHeap = psrc->pTypeMemHeap; @@ -65,11 +73,15 @@ pctxt->buffer.dynamic = TRUE; pctxt->buffer.byteIndex = 0; pctxt->buffer.bitOffset = 8; + + ast_mutex_unlock(&psrc->pLock); + /* ast_mutex_unlock(&pctxt->pLock); */ return stat; } void freeContext (OOCTXT* pctxt) { + ast_mutex_lock(&pctxt->pLock); ASN1BOOL saveBuf = (pctxt->flags & ASN1SAVEBUF) != 0; if (pctxt->buffer.dynamic && pctxt->buffer.data) { @@ -85,26 +97,36 @@ memHeapRelease (&pctxt->pTypeMemHeap); memHeapRelease (&pctxt->pMsgMemHeap); + + ast_mutex_unlock(&pctxt->pLock); + ast_mutex_destroy(&pctxt->pLock); } void copyContext (OOCTXT* pdest, OOCTXT* psrc) { + /* ast_mutex_lock(&pdest->pLock); ast_mutex_lock(&psrc->pLock); */ memcpy (&pdest->buffer, &psrc->buffer, sizeof(ASN1BUFFER)); pdest->flags = psrc->flags; + /* ast_mutex_unlock(&psrc->pLock); ast_mutex_unlock(&pdest->pLock); */ } void setCtxtFlag (OOCTXT* pctxt, ASN1USINT mask) { + ast_mutex_lock(&pctxt->pLock); pctxt->flags |= mask; + ast_mutex_unlock(&pctxt->pLock); } void clearCtxtFlag (OOCTXT* pctxt, ASN1USINT mask) { + ast_mutex_lock(&pctxt->pLock); pctxt->flags &= ~mask; + ast_mutex_unlock(&pctxt->pLock); } int setPERBufferUsingCtxt (OOCTXT* pTarget, OOCTXT* pSource) { + ast_mutex_lock(&pTarget->pLock); ast_mutex_lock(&pSource->pLock); int stat = initContextBuffer (pTarget, pSource->buffer.data, pSource->buffer.size); @@ -113,13 +135,16 @@ pTarget->buffer.bitOffset = pSource->buffer.bitOffset; } + ast_mutex_unlock(&pSource->pLock); ast_mutex_unlock(&pTarget->pLock); return stat; } int setPERBuffer (OOCTXT* pctxt, ASN1OCTET* bufaddr, ASN1UINT bufsiz, ASN1BOOL aligned) { + ast_mutex_lock(&pctxt->pLock); int stat = initContextBuffer (pctxt, bufaddr, bufsiz); + ast_mutex_unlock(&pctxt->pLock); if(stat != ASN_OK) return stat; @@ -128,10 +153,12 @@ OOCTXT* newContext () { - OOCTXT* pctxt = (OOCTXT*) ASN1CRTMALLOC0 (sizeof(OOCTXT)); + /* OOCTXT* pctxt = (OOCTXT*) ASN1CRTMALLOC0 (sizeof(OOCTXT)); */ + OOCTXT* pctxt = (OOCTXT*) malloc (sizeof(OOCTXT)); if (pctxt) { if (initContext(pctxt) != ASN_OK) { - ASN1CRTFREE0 (pctxt); + /* ASN1CRTFREE0 (pctxt); */ + free(pctxt); pctxt = 0; } pctxt->flags |= ASN1DYNCTXT; --- ./channels/ooh323c/src/perutil.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/perutil.c 2009-05-31 00:22:03.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "ooasn1.h" #include "ooper.h" --- ./channels/ooh323c/src/ootrace.h 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ootrace.h 2009-05-30 06:40:48.000000000 +0400 @@ -52,10 +52,11 @@ #define TRACELVL 1 #endif -#define OOTRACEERR1(a) ooTrace(OOTRCLVLERR,"%s", a) +#define OOTRACEERR1(a) ooTrace(OOTRCLVLERR,a) #define OOTRACEERR2(a,b) ooTrace(OOTRCLVLERR,a,b) #define OOTRACEERR3(a,b,c) ooTrace(OOTRCLVLERR,a,b,c) #define OOTRACEERR4(a,b,c,d) ooTrace(OOTRCLVLERR,a,b,c,d) +#define OOTRACEERR5(a,b,c,d,e) ooTrace(OOTRCLVLERR,a,b,c,d,e) #define OOTRACEWARN1(a) ooTrace(OOTRCLVLWARN,a) #define OOTRACEWARN2(a,b) ooTrace(OOTRCLVLWARN,a,b) #define OOTRACEWARN3(a,b,c) ooTrace(OOTRCLVLWARN,a,b,c) @@ -72,7 +73,7 @@ #define OOTRACEDBGA3(a,b,c) ooTrace(OOTRCLVLDBGA,a,b,c) #define OOTRACEDBGA4(a,b,c,d) ooTrace(OOTRCLVLDBGA,a,b,c,d) #define OOTRACEDBGA5(a,b,c,d,e) ooTrace(OOTRCLVLDBGA,a,b,c,d,e) -#define OOTRACEDBGB1(a) ooTrace(OOTRCLVLDBGB,"%s",a) +#define OOTRACEDBGB1(a) ooTrace(OOTRCLVLDBGB,a) #define OOTRACEDBGB2(a,b) ooTrace(OOTRCLVLDBGB,a,b) #define OOTRACEDBGB3(a,b,c) ooTrace(OOTRCLVLDBGB,a,b,c) #define OOTRACEDBGB4(a,b,c,d) ooTrace(OOTRCLVLDBGB,a,b,c,d) @@ -129,7 +130,7 @@ * * @return - none */ -EXTERN void ooTrace(OOUINT32 traceLevel, const char * fmtspec, ...)__attribute__((format(printf, 2, 3))); +EXTERN void ooTrace(OOUINT32 traceLevel, const char * fmtspec, ...); /** * Helper function for the trace function. This function performs actual --- ./channels/ooh323c/src/ooh245.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh245.c 2009-07-29 00:34:05.000000000 +0400 @@ -13,7 +13,8 @@ * maintain this copyright notice. * *****************************************************************************/ - +#include +#include #include "ooh245.h" #include "ooCalls.h" #include "printHandler.h" @@ -34,9 +35,10 @@ 6, { 0, 0, 8, 245, 0, 8 } }; -int ooCreateH245Message(H245Message **pph245msg, int type) +int ooCreateH245Message(OOH323CallData* call, H245Message **pph245msg, int type) { - OOCTXT* pctxt = &gH323ep.msgctxt; + /* OOCTXT* pctxt = &gH323ep.msgctxt; */ + OOCTXT* pctxt = call->msgctxt; *pph245msg = (H245Message*) memAlloc (pctxt, sizeof(H245Message)); @@ -121,7 +123,8 @@ OOTRACEDBGC1("msgCtxt Reset?"); if (0 != pmsg) { if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING)){ - memReset (&gH323ep.msgctxt); + /* memReset (&gH323ep.msgctxt); */ + memReset (call->msgctxt); OOTRACEDBGC3(" Done (%s, %s)\n", call->callType, call->callToken); return OO_OK; } @@ -166,7 +169,8 @@ int stat=0; ASN1OCTET* encodePtr=NULL; H245MultimediaSystemControlMessage *multimediaMsg; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; multimediaMsg = &(ph245Msg->h245Msg); if(!msgbuf || size<200) @@ -198,13 +202,15 @@ setPERBuffer (pctxt, msgbuf+i, (size-i), TRUE); - stat = asn1PE_H245MultimediaSystemControlMessage (&gH323ep.msgctxt, + /* stat = asn1PE_H245MultimediaSystemControlMessage (&gH323ep.msgctxt, */ + stat = asn1PE_H245MultimediaSystemControlMessage (call->msgctxt, multimediaMsg); if (stat != ASN_OK) { OOTRACEERR3 ("ERROR: H245 Message encoding failed (%s, %s)\n", call->callType, call->callToken); - OOTRACEERR1 (errGetText (&gH323ep.msgctxt)); + /* OOTRACEERR1 (errGetText (&gH323ep.msgctxt)); */ + OOTRACEERR1 (errGetText (call->msgctxt)); return OO_FAILED; } @@ -317,10 +323,11 @@ ooH323EpCapability *epCap=NULL; H245TerminalCapabilitySet *termCap=NULL; H245AudioCapability *audioCap=NULL; + H245DataApplicationCapability *t38Cap = NULL; H245AudioTelephonyEventCapability *ateCap=NULL; H245UserInputCapability *userInputCap = NULL; H245CapabilityTableEntry *entry=NULL; - H245AlternativeCapabilitySet *altSet=NULL; + H245AlternativeCapabilitySet *altSetAudio=NULL, *altSetVideo=NULL, *altSetDtmf=NULL; H245CapabilityDescriptor *capDesc=NULL; H245Message *ph245msg=NULL; H245VideoCapability *videoCap=NULL; @@ -333,7 +340,7 @@ return OO_OK; } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret == OO_FAILED) @@ -345,7 +352,8 @@ /* Set request type as TerminalCapabilitySet */ request = ph245msg->h245Msg.u.request; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; ph245msg->msgType = OOTerminalCapabilitySet; memset(request, 0, sizeof(H245RequestMessage)); if(request == NULL) @@ -366,6 +374,24 @@ termCap->sequenceNumber = ++(call->localTermCapSeqNo); termCap->protocolIdentifier = gh245ProtocolID; /* protocol id */ + /* Initialize alternate sets */ + altSetAudio = (H245AlternativeCapabilitySet*) + memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet)); + altSetVideo = (H245AlternativeCapabilitySet*) + memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet)); + altSetDtmf = (H245AlternativeCapabilitySet*) + memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet)); + if(!altSetAudio || !altSetVideo || !altSetDtmf) + { + OOTRACEERR3("Error:Memory - ooSendTermCapMsg - altSet." + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + memset(altSetDtmf, 0, sizeof(H245AlternativeCapabilitySet)); + memset(altSetVideo, 0, sizeof(H245AlternativeCapabilitySet)); + memset(altSetAudio, 0, sizeof(H245AlternativeCapabilitySet)); + + /* Add audio Capabilities */ dListInit(&(termCap->capabilityTable)); @@ -450,6 +476,82 @@ } entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetAudio->elem[altSetAudio->n] = i+1; + altSetAudio->n++; + i++; + } + else if(epCap->capType == OO_CAP_TYPE_DATA) + { + + /* Create t.38 capability. If capability supports receive, we only + add it as receive capability in TCS. However, if it supports only + transmit, we add it as transmit capability in TCS. + */ + if((epCap->dir & OORX) && !(epCap->dir & OOTX)) + { + + OOTRACEDBGC3("Sending receive capability t38 in TCS.(%s, %s)\n", + call->callType, call->callToken); + + t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OORX); + if(!t38Cap) + { + OOTRACEWARN3("WARN:Failed to create t38 capability for" + "%s, %s\n", + call->callType, call->callToken); + continue; + } + } + else if((epCap->dir & OOTX) && !(epCap->dir & OORX)) + { + OOTRACEDBGC3("Sending transmit capability t38 in TCS.(%s, %s)\n", + call->callType, call->callToken); + t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX); + if(!t38Cap) + { + OOTRACEWARN3("WARN:Failed to create capability t38 " + "(%s, %s)\n", + call->callType, call->callToken); + continue; + } + } + else{ + OOTRACEDBGC3("Sending transmit&recevie capability t38 in TCS.(%s, %s)\n", + call->callType, call->callToken); + t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX&OORX); + if(!t38Cap) + { + OOTRACEWARN3("WARN:Failed to create capability t38 " + "(%s, %s)\n", + call->callType, call->callToken); + continue; + } + } + /* Add Capabilities to Capability Table */ + entry = (H245CapabilityTableEntry*) memAlloc(pctxt, + sizeof(H245CapabilityTableEntry)); + if(!entry) + { + OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)." + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + memset(entry, 0, sizeof(H245CapabilityTableEntry)); + entry->m.capabilityPresent = 1; + if((epCap->dir & OORX) && (epCap->dir & OOTX)) { + entry->capability.t = T_H245Capability_receiveAndTransmitDataApplicationCapability; + entry->capability.u.receiveAndTransmitDataApplicationCapability = t38Cap; + } else if((epCap->dir & OORX)) { + entry->capability.t = T_H245Capability_receiveDataApplicationCapability; + entry->capability.u.receiveDataApplicationCapability = t38Cap; + }else{ + entry->capability.t = T_H245Capability_transmitDataApplicationCapability; + entry->capability.u.transmitDataApplicationCapability = t38Cap; + } + entry->capabilityTableEntryNumber = i+1; + dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetAudio->elem[altSetAudio->n] = i+1; + altSetAudio->n++; i++; } else if(epCap->capType == OO_CAP_TYPE_VIDEO) @@ -508,6 +610,8 @@ } entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetVideo->elem[altSetVideo->n] = i+1; + altSetVideo->n++; i++; } } @@ -541,6 +645,8 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -575,6 +681,8 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -609,6 +717,8 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -636,7 +746,7 @@ alternate capabilities set. Need a way for application developer to specify the alternative capability sets. */ - for(j=0; jelem[0] = j+1; dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSet); - } + } */ + + if (altSetAudio->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetAudio); + if (altSetVideo->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetVideo); + if (altSetDtmf->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetDtmf); dListInit(&(termCap->capabilityDescriptors)); dListAppend(pctxt, &(termCap->capabilityDescriptors), capDesc); @@ -695,7 +809,7 @@ { H245MasterSlaveDetermination *masterSlave; H245MasterSlaveDeterminationAck *masterSlaveAck; - ASN1UINT statusDeterminationNumber; + ASN1UINT statusDeterminationNumber, moduloDiff; switch(msgType) { @@ -704,7 +818,16 @@ call->callType, call->callToken); masterSlave = (H245MasterSlaveDetermination*)pmsg; - + + if(call->masterSlaveState != OO_MasterSlave_DetermineSent && + OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER)) + { + ooSendMasterSlaveDeterminationAck(call, "slave"); + call->masterSlaveState = OO_MasterSlave_Master; + OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n", + call->callType, call->callToken); + return OO_OK; + } if(masterSlave->terminalType < gH323ep.termType) { ooSendMasterSlaveDeterminationAck(call, "slave"); @@ -730,10 +853,17 @@ if(call->masterSlaveState == OO_MasterSlave_DetermineSent) statusDeterminationNumber = call->statusDeterminationNumber; else - statusDeterminationNumber = ooGenerateStatusDeterminationNumber(); + if (OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER)) + statusDeterminationNumber = masterSlave->statusDeterminationNumber - 1; + else + statusDeterminationNumber = ooGenerateStatusDeterminationNumber(); + + moduloDiff = (masterSlave->statusDeterminationNumber - statusDeterminationNumber) + &0xffffff; - if(masterSlave->statusDeterminationNumber < - statusDeterminationNumber) + /* if(masterSlave->statusDeterminationNumber > + statusDeterminationNumber) */ + if (moduloDiff < 0x800000 && moduloDiff != 0) { ooSendMasterSlaveDeterminationAck(call, "slave"); call->masterSlaveState = OO_MasterSlave_Master; @@ -741,8 +871,9 @@ call->callType, call->callToken); return OO_OK; } - if(masterSlave->statusDeterminationNumber > - statusDeterminationNumber) + /* if(masterSlave->statusDeterminationNumber < + statusDeterminationNumber) */ + if (moduloDiff > 0x800000) { ooSendMasterSlaveDeterminationAck(call, "master"); call->masterSlaveState = OO_MasterSlave_Slave; @@ -750,8 +881,9 @@ call->callType, call->callToken); return OO_OK; } - if(masterSlave->statusDeterminationNumber == - statusDeterminationNumber) + /* if(masterSlave->statusDeterminationNumber == + statusDeterminationNumber) */ + if (moduloDiff == 0 || moduloDiff == 0x800000) { ooSendMasterSlaveDeterminationReject (call); @@ -780,6 +912,8 @@ call->callType, call->callToken); } } + + call->msAckStatus = OO_msAck_remoteReceived; if(call->localTermCapState == OO_LocalTermCapSetAckRecvd && call->remoteTermCapState == OO_RemoteTermCapSetAckSent) @@ -816,7 +950,8 @@ int ret; H245Message* ph245msg=NULL; H245RequestMessage *request; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; H245MasterSlaveDetermination* pMasterSlave; /* Check whether Master Slave Determination already in progress */ @@ -827,7 +962,7 @@ return OO_OK; } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -873,9 +1008,10 @@ int ret=0; H245ResponseMessage * response=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -910,6 +1046,7 @@ } ooFreeH245Message(call, ph245msg); + call->msAckStatus = OO_msAck_localSent; return ret; } @@ -918,10 +1055,11 @@ int ret=0; H245ResponseMessage* response=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_response); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - MasterSlave " @@ -963,10 +1101,11 @@ int ret=0; H245IndicationMessage* indication=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_indication); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - MasterSlave " @@ -1028,6 +1167,260 @@ return OO_OK; } +/* handling requestmode routines */ + +int ooSendRequestModeAck(OOH323CallData* call, + H245SequenceNumber sequenceNumber) +{ + int ret=0; + H245ResponseMessage* response=NULL; + H245Message *ph245msg=NULL; + OOCTXT *pctxt=call->msgctxt; + + ret = ooCreateH245Message(call, &ph245msg, + T_H245MultimediaSystemControlMessage_response); + if(ret != OO_OK) + { + OOTRACEERR3("Error:H245 message creation failed for - RequestMode " + "Ack (%s, %s)\n",call->callType, + call->callToken); + return OO_FAILED; + } + ph245msg->msgType = OORequestModeAck; + response = ph245msg->h245Msg.u.response; + memset(response, 0, sizeof(H245ResponseMessage)); + response->t = T_H245ResponseMessage_requestModeAck; + response->u.requestModeAck = (H245RequestModeAck *) + ASN1MALLOC(pctxt, sizeof(H245RequestModeAck)); + memset(response->u.requestModeAck, 0, + sizeof(H245RequestModeAck)); + + response->u.requestModeAck->sequenceNumber = sequenceNumber; + response->u.requestModeAck->response.t = + T_H245RequestModeAck_response_willTransmitMostPreferredMode; + + OOTRACEDBGA3("Built RequestModeAck (%s, %s)\n", + call->callType, call->callToken); + ret = ooSendH245Msg(call, ph245msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error:Failed to enqueue RequestModeAck message" + " to outbound queue. (%s, %s)\n", call->callType, + call->callToken); + } + + ooFreeH245Message(call, ph245msg); + return ret; +} + +int ooSendRequestModeReject(OOH323CallData* call, + H245SequenceNumber sequenceNumber) +{ + int ret=0; + H245ResponseMessage* response=NULL; + H245Message *ph245msg=NULL; + OOCTXT *pctxt=call->msgctxt; + + ret = ooCreateH245Message(call, &ph245msg, + T_H245MultimediaSystemControlMessage_response); + if(ret != OO_OK) + { + OOTRACEERR3("Error:H245 message creation failed for - RequstMode " + "Reject (%s, %s)\n",call->callType, + call->callToken); + return OO_FAILED; + } + ph245msg->msgType = OORequestModeReject; + response = ph245msg->h245Msg.u.response; + memset(response, 0, sizeof(H245ResponseMessage)); + response->t = T_H245ResponseMessage_requestModeReject; + response->u.requestModeReject = (H245RequestModeReject *) + ASN1MALLOC(pctxt, sizeof(H245RequestModeReject)); + memset(response->u.requestModeReject, 0, + sizeof(H245RequestModeReject)); + + response->u.requestModeReject->sequenceNumber = sequenceNumber; + response->u.requestModeReject->cause.t = + T_H245RequestModeReject_cause_modeUnavailable; + + OOTRACEDBGA3("Built RequestModeReject (%s, %s)\n", + call->callType, call->callToken); + ret = ooSendH245Msg(call, ph245msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error:Failed to enqueue RequestModeReject message" + " to outbound queue. (%s, %s)\n", call->callType, + call->callToken); + } + + ooFreeH245Message(call, ph245msg); + return ret; +} + +int ooSendRequestMode(OOH323CallData* call, + int isT38Mode) +{ + int ret=0; + H245RequestMessage *request; + H245Message *ph245msg=NULL; + OOCTXT *pctxt=call->msgctxt; + + + H245ModeDescription pModeDesc; + H245ModeElement pModeElem; + H245ModeElement* pModeElemRef = &pModeElem; + + if (isT38Mode && !OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) /* t38 req but we dont support */ + return OO_OK; + + ret = ooCreateH245Message(call, &ph245msg, + T_H245MultimediaSystemControlMessage_request); + if(ret != OO_OK) + { + OOTRACEERR3("Error:H245 message creation failed for - RequstMode " + "(%s, %s)\n",call->callType, + call->callToken); + return OO_FAILED; + } + ph245msg->msgType = OORequestMode; + request = ph245msg->h245Msg.u.request; + memset(request, 0, sizeof(H245RequestMessage)); + request->t = T_H245RequestMessage_requestMode; + + request->u.requestMode = (H245RequestMode *) + ASN1MALLOC(pctxt, sizeof(H245RequestMode)); + memset(request->u.requestMode, 0, + sizeof(H245RequestMode)); + + call->requestSequence++; + call->reqFlags = (isT38Mode) ? OO_M_DATASESSION : OO_M_AUDIOSESSION; + + request->u.requestMode->sequenceNumber = call->requestSequence; + memset(&pModeElem, 0, sizeof(pModeElem)); + memset(&pModeDesc, 0, sizeof(pModeDesc)); + dListInit(&(request->u.requestMode->requestedModes)); + dListInit(&pModeDesc); + + if (isT38Mode) { + + pModeElem.type.t = T_H245ModeElementType_dataMode; + pModeElem.type.u.dataMode = (H245DataMode *) memAllocZ(pctxt, sizeof(H245DataMode)); + pModeElem.type.u.dataMode->bitRate = 144; + if (!ooCreateT38ApplicationData(pctxt, + (H245DataApplicationCapability_application*) &(pModeElem.type.u.dataMode->application))) { + OOTRACEERR3("Error:Memory - ooCapabilityCreateT38Capability - (%s, %s)\n", + call->callType, + call->callToken); + } + } else { + pModeElem.type.t = T_H245ModeElementType_audioMode; + pModeElem.type.u.audioMode = (H245AudioMode *) memAllocZ(pctxt, sizeof(H245AudioMode)); + pModeElem.type.u.audioMode->t = T_H245AudioMode_genericAudioMode; + pModeElem.type.u.audioMode->u.genericAudioMode = (H245GenericCapability *) + memAllocZ(pctxt, sizeof(H245GenericCapability)); + pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.t = + T_H245CapabilityIdentifier_domainBased; + pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.u.domainBased = + "H.323"; + pModeElem.type.u.audioMode->u.genericAudioMode->m.maxBitRatePresent = TRUE; + pModeElem.type.u.audioMode->u.genericAudioMode->maxBitRate = 144; + } + + dListAppend(pctxt, &pModeDesc, &pModeElem); + dListAppend(pctxt, &(request->u.requestMode->requestedModes), &pModeDesc); + + ret = ooSendH245Msg(call, ph245msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error:Failed to enqueue RequestMode message" + " to outbound queue. (%s, %s)\n", call->callType, + call->callToken); + } + + ooFreeH245Message(call, ph245msg); + return ret; +} + +void ooOnReceivedRequestModeAck(OOH323CallData* call, H245RequestModeAck * requestModeAck) +{ + int t38mode; + + if (!call->reqFlags) return; + + if (OO_TESTFLAG(call->reqFlags, OO_M_AUDIOSESSION)) { + OO_SETFLAG(call->flags, OO_M_AUDIOSESSION); + OO_CLRFLAG(call->flags, OO_M_DATASESSION); + t38mode = 0; + } else { + OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION); + OO_SETFLAG(call->flags, OO_M_DATASESSION); + t38mode = 1; + } + + call->reqFlags = 0; /* don't handle duplicate ack packet */ + + ooCloseAllLogicalChannels(call, "transmit"); + if(gH323ep.h323Callbacks.onModeChanged) { + OOTRACEDBGA3("Handle RequestModeAck: (%s, %s), calling " + "callback onModeChanged\n", call->callType, call->callToken); + gH323ep.h323Callbacks.onModeChanged(call, t38mode); + } +} + +int ooHandleRequestMode(OOH323CallData* call, + H245RequestMode *requestMode) +{ + + H245ModeDescription** pModeRef; + H245ModeElement** pModeElem; + H245ModeElementType* pMode; + int ret = 0; + + pModeRef = (H245ModeDescription**)dListFindByIndex(&requestMode->requestedModes, 0); + pModeElem = (H245ModeElement **) dListFindByIndex(*pModeRef, 0); + pMode = &((*pModeElem)->type); + OOTRACEDBGA5("Handle RequestMode: " + " modetype: %d/%d for (%s, %s)\n", pMode->t, pMode->u.dataMode->application.t, + call->callType, + call->callToken); + switch (pMode->t) { + case T_H245ModeElementType_dataMode: + if (pMode->u.dataMode->application.t == T_H245DataMode_application_t38fax && + OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) { + if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK && + OO_TESTFLAG(call->flags, OO_M_AUDIOSESSION)) { + + OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION); + OO_SETFLAG(call->flags, OO_M_DATASESSION); + if(gH323ep.h323Callbacks.onModeChanged) { + OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling " + "callback onModeChanged\n", call->callType, call->callToken); + gH323ep.h323Callbacks.onModeChanged(call, 1); + } + } + } else { + ooSendRequestModeReject(call, requestMode->sequenceNumber); + } + break; + case T_H245ModeElementType_audioMode: + if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK && + OO_TESTFLAG(call->flags, OO_M_DATASESSION)) { + + OO_CLRFLAG(call->flags, OO_M_DATASESSION); + OO_SETFLAG(call->flags, OO_M_AUDIOSESSION); + if(gH323ep.h323Callbacks.onModeChanged) { + OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling " + "callback onModeChanged\n", call->callType, call->callToken); + gH323ep.h323Callbacks.onModeChanged(call, 0); + } + } + break; + default: + ; + } + return OO_OK; + +} int ooHandleOpenLogicalChannel(OOH323CallData* call, H245OpenLogicalChannel *olc) @@ -1062,14 +1455,8 @@ break; case T_H245DataType_videoData: case T_H245DataType_audioData: - ooHandleOpenLogicalChannel_helper(call, olc); - break; case T_H245DataType_data: - OOTRACEWARN3("Warn:Media channel data type " - "'T_H245DataType_data' not supported (%s, %s)\n", - call->callType, call->callToken); - ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber, - T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported); + ooHandleOpenLogicalChannel_helper(call, olc); break; case T_H245DataType_encryptionData: OOTRACEWARN3("Warn:Media channel data type " @@ -1168,7 +1555,7 @@ return OO_FAILED; } /* Generate an Ack for the open channel request */ - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -1183,7 +1570,8 @@ ph245msg->msgType = OOOpenLogicalChannelAck; ph245msg->logicalChannelNo = olc->forwardLogicalChannelNumber; response = ph245msg->h245Msg.u.response; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; memset(response, 0, sizeof(H245ResponseMessage)); response->t = T_H245ResponseMessage_openLogicalChannelAck; response->u.openLogicalChannelAck = (H245OpenLogicalChannelAck*) @@ -1292,10 +1680,11 @@ int ret=0; H245ResponseMessage* response=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_response); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - OpenLogicalChannel" @@ -1351,7 +1740,7 @@ H245UnicastAddress *unicastAddr; H245UnicastAddress_iPAddress *iPAddress; H245UnicastAddress *unicastAddr1; - H245UnicastAddress_iPAddress *iPAddress1; + H245UnicastAddress_iPAddress *iPAddress1 = NULL; if(!((olcAck->m.forwardMultiplexAckParametersPresent == 1) && (olcAck->forwardMultiplexAckParameters.t == @@ -1396,30 +1785,29 @@ iPAddress->network.data[3]); /* Extract media control channel address */ - if(h2250lcap->m.mediaControlChannelPresent != 1) - { - OOTRACEERR3("Error: Processing OpenLogicalChannelAck - Missing media " - "control channel (%s, %s)\n", call->callType, call->callToken); - return OO_FAILED; - } - if(h2250lcap->mediaControlChannel.t != + if(h2250lcap->m.mediaControlChannelPresent == 1) { + if(h2250lcap->mediaControlChannel.t != T_H245TransportAddress_unicastAddress) - { - OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control " + { + OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control " "channel addres type is not unicast (%s, %s)\n", call->callType, call->callToken); - return OO_FAILED; - } + return OO_FAILED; + } - unicastAddr1 = h2250lcap->mediaControlChannel.u.unicastAddress; - if(unicastAddr1->t != T_H245UnicastAddress_iPAddress) - { - OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control " + unicastAddr1 = h2250lcap->mediaControlChannel.u.unicastAddress; + if(unicastAddr1->t != T_H245UnicastAddress_iPAddress) { + OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control " "channel address type is not IP (%s, %s)\n", call->callType, call->callToken); - return OO_FAILED; + return OO_FAILED; + } + + iPAddress1 = unicastAddr1->u.iPAddress; + } else { + OOTRACEDBGA3("Warning: Processing OpenLogicalChannelAck - Missing media " + "control channel (%s, %s)\n", call->callType, call->callToken); } - iPAddress1 = unicastAddr1->u.iPAddress; /* Set remote destination address for rtp session */ // strcpy(call->remoteIP, remoteip); @@ -1442,7 +1830,8 @@ /* Populate ports &ip for channel */ strcpy(pLogicalChannel->remoteIP, remoteip); pLogicalChannel->remoteMediaPort = iPAddress->tsapIdentifier; - pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier; + if (iPAddress1) + pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier; if(pLogicalChannel->chanCap->startTransmitChannel) { @@ -1567,7 +1956,7 @@ H245CommandMessage * command; OOCTXT *pctxt; H245Message *ph245msg=NULL; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_command); if(ret != OO_OK) { @@ -1578,7 +1967,8 @@ ph245msg->msgType = OOEndSessionCommand; command = ph245msg->h245Msg.u.command; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; memset(command, 0, sizeof(H245CommandMessage)); command->t = T_H245CommandMessage_endSessionCommand; command->u.endSessionCommand = (H245EndSessionCommand*) ASN1MALLOC(pctxt, @@ -1675,8 +2065,9 @@ if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent) return OO_OK; - if(call->masterSlaveState == OO_MasterSlave_Master || - call->masterSlaveState == OO_MasterSlave_Slave) + if((call->masterSlaveState == OO_MasterSlave_Master || + call->masterSlaveState == OO_MasterSlave_Slave) && + (call->msAckStatus == OO_msAck_remoteReceived)) { if(gH323ep.h323Callbacks.openLogicalChannels) gH323ep.h323Callbacks.openLogicalChannels(call); @@ -1697,14 +2088,15 @@ return OO_OK; } -int ooCloseAllLogicalChannels(OOH323CallData *call) +int ooCloseAllLogicalChannels(OOH323CallData *call, char* dir) { ooLogicalChannel *temp; temp = call->logicalChans; while(temp) { - if(temp->state == OO_LOGICALCHAN_ESTABLISHED) + if(temp->state == OO_LOGICALCHAN_ESTABLISHED && + (dir == NULL || !strcmp(temp->dir,dir))) { /* Sending closelogicalchannel only for outgoing channels*/ if(!strcmp(temp->dir, "transmit")) @@ -1728,7 +2120,7 @@ H245RequestMessage *request; H245CloseLogicalChannel* clc; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -1738,7 +2130,8 @@ } ph245msg->msgType = OOCloseLogicalChannel; ph245msg->logicalChannelNo = logicalChan->channelNo; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; request = ph245msg->h245Msg.u.request; request->t = T_H245RequestMessage_closeLogicalChannel; @@ -1795,7 +2188,7 @@ H245RequestMessage *request; H245RequestChannelClose *rclc; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -1806,7 +2199,8 @@ } ph245msg->msgType = OORequestChannelClose; ph245msg->logicalChannelNo = logicalChan->channelNo; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; request = ph245msg->h245Msg.u.request; request->t = T_H245RequestMessage_requestChannelClose; @@ -1848,7 +2242,7 @@ OOCTXT *pctxt; H245IndicationMessage *indication; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if(ret != OO_OK) { @@ -1859,7 +2253,8 @@ } ph245msg->msgType = OORequestChannelCloseRelease; ph245msg->logicalChannelNo = channelNum; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; indication = ph245msg->h245Msg.u.indication; indication->t = T_H245IndicationMessage_requestChannelCloseRelease; indication->u.requestChannelCloseRelease = (H245RequestChannelCloseRelease*) @@ -1919,7 +2314,7 @@ return OO_FAILED; } } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -1927,7 +2322,8 @@ "failed (%s, %s)\n", call->callType, call->callToken); return OO_FAILED; } - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; ph245msg->msgType = OORequestChannelCloseAck; ph245msg->logicalChannelNo = rclc->forwardLogicalChannelNumber; response = ph245msg->h245Msg.u.response; @@ -2055,7 +2451,7 @@ return OO_FAILED; } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -2064,7 +2460,8 @@ call->callToken); return OO_FAILED; } - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; ph245msg->msgType = OOCloseLogicalChannelAck; ph245msg->logicalChannelNo = clc->forwardLogicalChannelNumber; response = ph245msg->h245Msg.u.response; @@ -2144,13 +2541,23 @@ case T_H245RequestMessage_openLogicalChannel: ooHandleOpenLogicalChannel(call, request->u.openLogicalChannel); + if(!ooGetTransmitLogicalChannel(call)) + ooOpenLogicalChannels(call); break; + case T_H245RequestMessage_requestMode: + OOTRACEINFO4("Received request mode - %d (%s, %s)\n", + request->u.requestMode->sequenceNumber, call->callType, call->callToken); + ooHandleRequestMode(call, + request->u.requestMode); + break; case T_H245RequestMessage_closeLogicalChannel: OOTRACEINFO4("Received close logical Channel - %d (%s, %s)\n", request->u.closeLogicalChannel->forwardLogicalChannelNumber, call->callType, call->callToken); - ooOnReceivedCloseLogicalChannel(call, - request->u.closeLogicalChannel); + if (ooOnReceivedCloseLogicalChannel(call, + request->u.closeLogicalChannel) == OO_OK) { + ooCloseAllLogicalChannels(call, NULL); + } break; case T_H245RequestMessage_requestChannelClose: OOTRACEINFO4("Received RequestChannelClose - %d (%s, %s)\n", @@ -2255,6 +2662,21 @@ call->callEndReason = OO_REASON_NOCOMMON_CAPABILITIES; } break; + case T_H245ResponseMessage_requestModeAck: + if (call->requestSequence == response->u.requestModeAck->sequenceNumber) { + /* response to our last request, process it */ + ooOnReceivedRequestModeAck(call, response->u.requestModeAck); + } + break; + case T_H245ResponseMessage_requestModeReject: + OOTRACEDBGC3("Received requestModeReject, clearing call (%s, %s)\n", + call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_REMOTE_REJECTED; + } + break; case T_H245ResponseMessage_openLogicalChannelAck: for(i = 0; itimerList.count; i++) { @@ -2474,6 +2896,10 @@ } } + if (call->t38sides == 3) /* both side support t.38 */ + OO_SETFLAG(call->flags, OO_M_T38SUPPORTED); + else + OO_CLRFLAG(call->flags, OO_M_T38SUPPORTED); /* Update remoteTermCapSetState */ call->remoteTermCapState = OO_RemoteTermCapSetRecvd; @@ -2527,7 +2953,7 @@ H245Message *ph245msg=NULL; H245ResponseMessage * response=NULL; OOCTXT *pctxt=NULL; - int ret = ooCreateH245Message(&ph245msg, + int ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -2538,7 +2964,8 @@ ph245msg->msgType = OOTerminalCapabilitySetReject; response = ph245msg->h245Msg.u.response; memset(response, 0, sizeof(H245ResponseMessage)); - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; response->t = T_H245ResponseMessage_terminalCapabilitySetReject; response->u.terminalCapabilitySetReject = (H245TerminalCapabilitySetReject*) @@ -2570,7 +2997,7 @@ H245Message *ph245msg=NULL; H245ResponseMessage * response=NULL; OOCTXT *pctxt=NULL; - int ret = ooCreateH245Message(&ph245msg, + int ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -2581,7 +3008,8 @@ ph245msg->msgType = OOTerminalCapabilitySetAck; response = ph245msg->h245Msg.u.response; memset(response, 0, sizeof(H245ResponseMessage)); - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; response->t = T_H245ResponseMessage_terminalCapabilitySetAck; response->u.terminalCapabilitySetAck = (H245TerminalCapabilitySetAck*) @@ -2612,10 +3040,11 @@ int ret=0; H245IndicationMessage* indication=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_indication); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - Terminal" @@ -2662,10 +3091,11 @@ int ret=0; H245IndicationMessage* indication=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_indication); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - H245UserInput" @@ -2721,10 +3151,11 @@ int ret=0; H245IndicationMessage* indication=NULL; H245Message *ph245msg=NULL; - OOCTXT *pctxt=&gH323ep.msgctxt; + /* OOCTXT *pctxt=&gH323ep.msgctxt; */ + OOCTXT *pctxt=call->msgctxt; ret = ooCreateH245Message - (&ph245msg, T_H245MultimediaSystemControlMessage_indication); + (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if (ret != OO_OK) { OOTRACEERR3("Error:H245 message creation failed for - H245UserInput" @@ -2788,21 +3219,20 @@ if(gH323ep.callMode == OO_CALLMODE_AUDIOCALL || gH323ep.callMode == OO_CALLMODE_AUDIOTX) { - //if (!OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) - //{ + if (OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) { ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO); - if(ret != OO_OK) - { - OOTRACEERR3("ERROR:Failed to open audio channels. Clearing call." - "(%s, %s)\n", call->callType, call->callToken); - if(call->callState < OO_CALL_CLEAR) - { - call->callEndReason = OO_REASON_LOCAL_CLEARED; - call->callState = OO_CALL_CLEAR; - } - return ret; - } - // } + } else if (OO_TESTFLAG (call->flags, OO_M_DATASESSION)) { + ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_DATA); + } + if(ret != OO_OK) { + OOTRACEERR3("ERROR:Failed to open audio/data channels. Clearing call." + "(%s, %s)\n", call->callType, call->callToken); + if (call->callState < OO_CALL_CLEAR) { + call->callEndReason = OO_REASON_LOCAL_CLEARED; + call->callState = OO_CALL_CLEAR; + } + return ret; + } } if(gH323ep.callMode == OO_CALLMODE_VIDEOCALL) @@ -2860,6 +3290,7 @@ */ OOTRACEINFO3("Looking for matching capabilities. (%s, %s)\n", call->callType, call->callToken); +/* May */ if(call->masterSlaveState == OO_MasterSlave_Master) { for(k=0; kcapPrefs.index; k++) @@ -2924,17 +3355,21 @@ case OO_G711ALAW56K: case OO_G711ULAW64K: case OO_G711ULAW56K: - /*case OO_G726:*/ + case OO_G726: + case OO_G726AAL2: + case OO_AMRNB: case OO_G728: case OO_G729: case OO_G729A: + case OO_G729B: case OO_G7231: case OO_GSMFULLRATE: + case OO_GSMHALFRATE: + case OO_GSMENHANCEDFULLRATE: case OO_H263VIDEO: + case OO_T38: ooOpenChannel(call, epCap); break; - case OO_GSMHALFRATE: - case OO_GSMENHANCEDFULLRATE: default: @@ -2953,6 +3388,7 @@ H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp = NULL; H245AudioCapability *audioCap = NULL; H245VideoCapability *videoCap = NULL; + H245DataApplicationCapability *t38Cap = NULL; H245H2250LogicalChannelParameters *h2250lcp = NULL; H245UnicastAddress *unicastAddrs = NULL; H245UnicastAddress_iPAddress *iPAddress = NULL; @@ -2963,7 +3399,7 @@ ooGetCapTypeText(epCap->cap), call->callType, call->callToken); - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -2980,7 +3416,8 @@ call->logicalChanNoCur = call->logicalChanNoBase; request = ph245msg->h245Msg.u.request; - pctxt = &gH323ep.msgctxt; + /* pctxt = &gH323ep.msgctxt; */ + pctxt = call->msgctxt; memset(request, 0, sizeof(H245RequestMessage)); request->t = T_H245RequestMessage_openLogicalChannel; @@ -3053,6 +3490,23 @@ flcp->dataType.u.videoData = videoCap; } + else if(epCap->capType == OO_CAP_TYPE_DATA) + { + flcp->dataType.t = T_H245DataType_data; + /* set audio capability for channel */ + t38Cap = ooCapabilityCreateT38Capability(epCap,pctxt, OOTX); + if(!t38Cap) + { + OOTRACEERR4("Error:Failed to create duplicate T38 capability in " + "ooOpenChannel- %s (%s, %s)\n", + ooGetCapTypeText(epCap->cap), call->callType, + call->callToken); + ooFreeH245Message(call, ph245msg); + return OO_FAILED; + } + + flcp->dataType.u.data = t38Cap; + } else{ OOTRACEERR1("Error: Unhandled media type in ooOpenChannel\n"); return OO_FAILED; @@ -3104,7 +3558,7 @@ } ooFreeH245Message(call, ph245msg); - return ret; + return ret; } @@ -3447,13 +3901,20 @@ int ooRequestChannelCloseTimerExpired(void *pdata) { int ret = 0; + ooLogicalChannel *pChannel = NULL; ooTimerCallback *cbData = (ooTimerCallback*)pdata; OOH323CallData *call = cbData->call; - OOTRACEINFO3("OpenLogicalChannelTimer expired. (%s, %s)\n", call->callType, + OOTRACEINFO3("CloseLogicalChannelTimer expired. (%s, %s)\n", call->callType, call->callToken); - ooSendRequestChannelCloseRelease(call, cbData->channelNumber); + pChannel = ooFindLogicalChannelByLogicalChannelNo(call, + cbData->channelNumber); + if(pChannel) + ooSendRequestChannelCloseRelease(call, cbData->channelNumber); + else + return OO_OK; + ret = ooClearLogicalChannel(call, cbData->channelNumber); if(ret != OO_OK) --- ./channels/ooh323c/src/ooh323.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh323.h 2009-07-03 23:45:42.000000000 +0400 @@ -122,6 +122,11 @@ OOAliases **aliasList); /** + */ +EXTERN int ooPopulatePrefixList(OOCTXT *pctxt, OOAliases *pAliases, + H225_SeqOfH225SupportedPrefix *pPrefixList ); + +/** * This is a helper function used to populate alias list using aliases. * @param pctxt Pointer to OOCTXT structure which will be used for memory * allocations. --- ./channels/ooh323c/src/ootrace.c 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ootrace.c 2009-05-31 00:19:24.000000000 +0400 @@ -14,6 +14,8 @@ * *****************************************************************************/ +#include +#include #include #include #include @@ -70,7 +72,7 @@ #else struct tm *ptime; - char dateString[15]; + char dateString[10]; time_t t = time(NULL); ptime = localtime(&t); strftime(timeString, 100, "%H:%M:%S", ptime); @@ -100,7 +102,7 @@ if(printDate) { printDate = 0; - strftime(dateString, 15, "%m/%d/%Y", ptime); + strftime(dateString, 10, "%D", ptime); fprintf(gH323ep.fptraceFile, "---------Date %s---------\n", dateString); } --- ./channels/ooh323c/src/eventHandler.c 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/eventHandler.c 2009-05-31 00:22:13.000000000 +0400 @@ -14,6 +14,9 @@ * *****************************************************************************/ +#include +#include + #include "eventHandler.h" void setEventHandler (OOCTXT* pctxt, EventHandler* pHandler) --- ./channels/ooh323c/src/ooh323ep.h 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooh323ep.h 2009-07-11 04:42:18.000000000 +0400 @@ -26,12 +26,12 @@ #include "ooq931.h" #define DEFAULT_TRACEFILE "trace.log" -#define DEFAULT_TERMTYPE 50 -#define DEFAULT_PRODUCTID "objsys" +#define DEFAULT_TERMTYPE 60 +#define DEFAULT_PRODUCTID "ooh323" #define DEFAULT_CALLERID "objsyscall" -#define DEFAULT_T35COUNTRYCODE 1 +#define DEFAULT_T35COUNTRYCODE 184 #define DEFAULT_T35EXTENSION 0 -#define DEFAULT_MANUFACTURERCODE 71 +#define DEFAULT_MANUFACTURERCODE 39 #define DEFAULT_H245CONNECTION_RETRYTIMEOUT 2 #define DEFAULT_CALLESTB_TIMEOUT 60 #define DEFAULT_MSD_TIMEOUT 30 @@ -58,8 +58,8 @@ * @{ */ /* Default port ranges */ -#define TCPPORTSSTART 12030 /*!< Starting TCP port number */ -#define TCPPORTSEND 12230 /*!< Ending TCP port number */ +#define TCPPORTSSTART 12000 /*!< Starting TCP port number */ +#define TCPPORTSEND 62230 /*!< Ending TCP port number */ #define UDPPORTSSTART 13030 /*!< Starting UDP port number */ #define UDPPORTSEND 13230 /*!< Ending UDP port number */ #define RTPPORTSSTART 14030 /*!< Starting RTP port number */ @@ -170,7 +170,10 @@ * * @return OO_OK, on success. OO_FAILED, on failure. */ -EXTERN int ooH323EpSetAsGateway(); +EXTERN int ooH323EpSetAsGateway(void); + +EXTERN int ooH323EpSetVersionInfo(int t35countrycode, int t35extensions, int manufacturer, + char* vendor, char* version); /** * This function is used to assign a local ip address to be used for call @@ -378,6 +381,13 @@ EXTERN int ooH323EpDisableH245Tunneling(void); /** + * This function is used to setup/clear TryBeMaster flag + * + * @return OO_OK, on success. OO_FAILED, on failure. + */ +EXTERN int ooH323EpTryBeMaster(int); + +/** * This function is used to enable GkRouted calls. * * @return OO_OK, on success. OO_FAILED, on failure. @@ -589,28 +599,28 @@ * the endpoint. * @return OO_OK, on success; OO_FAILED, on failure */ -EXTERN int ooH323EpEnableDTMFH245Alphanumeric(); +EXTERN int ooH323EpEnableDTMFH245Alphanumeric(void); /** * This function is used to disable the H245(alphanumeric) dtmf capability for * the endpoint. * @return OO_OK, on success; OO_FAILED, on failure */ -EXTERN int ooH323EpDisableDTMFH245Alphanumeric(); +EXTERN int ooH323EpDisableDTMFH245Alphanumeric(void); /** * This function is used to enable the H245(signal) dtmf capability for * the endpoint. * @return OO_OK, on success; OO_FAILED, on failure */ -EXTERN int ooH323EpEnableDTMFH245Signal(); +EXTERN int ooH323EpEnableDTMFH245Signal(void); /** * This function is used to disable the H245(signal) dtmf capability for * the endpoint. * @return OO_OK, on success; OO_FAILED, on failure */ -EXTERN int ooH323EpDisableDTMFH245Signal(); +EXTERN int ooH323EpDisableDTMFH245Signal(void); /** * This function is used to add callbacks to the gatekeeper client. If user --- ./channels/ooh323c/src/ooGkClient.c 2008-05-28 18:45:23.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooGkClient.c 2009-07-03 23:50:45.000000000 +0400 @@ -20,6 +20,9 @@ * This file contains functions to support RAS protocol. * */ +#include +#include + #include "ooGkClient.h" #include "ootypes.h" #include "ootrace.h" @@ -58,6 +61,7 @@ } memset(pGkClient, 0, sizeof(ooGkClient)); + ast_mutex_init(&pGkClient->Lock); gH323ep.gkClient = pGkClient; initContext(&(pGkClient->ctxt)); initContext(&(pGkClient->msgCtxt)); @@ -156,7 +160,7 @@ pGkClient->gkRasPort); } else if(pGkClient->gkMode == RasDiscoverGatekeeper) { - OOTRACEINFO1("\tGatekeeper mode - UseSpecificGatekeeper\n"); + OOTRACEINFO1("\tGatekeeper mode - RasDiscoverGatekeeper\n"); } else { OOTRACEERR1("Invalid GatekeeperMode\n"); @@ -177,6 +181,9 @@ ooGkClientCloseChannel(gH323ep.gkClient); freeContext(&gH323ep.gkClient->msgCtxt); freeContext(&gH323ep.gkClient->ctxt); + ast_mutex_lock(&gH323ep.gkClient->Lock); + ast_mutex_unlock(&gH323ep.gkClient->Lock); + ast_mutex_destroy(&gH323ep.gkClient->Lock); memFreePtr(&gH323ep.ctxt, gH323ep.gkClient); gH323ep.gkClient = NULL; } @@ -194,14 +201,17 @@ return OO_FAILED; } + ast_mutex_lock(&pGkClient->Lock); pGkClient->discoveryComplete = FALSE; iRet = ooGkClientSendGRQ(pGkClient); if(iRet != OO_OK) { OOTRACEERR1("Error:Failed to send GRQ message\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -236,6 +246,7 @@ else if(eGkMode == RasNoGatekeeper) { OOTRACEINFO1("Gatekeeper Mode - RasNoGatekeeper\n"); } + return OO_OK; } @@ -361,6 +372,7 @@ H225RasMessage *pRasMsg=NULL; int iRet=OO_OK; + ast_mutex_lock(&pGkClient->Lock); pctxt = &pGkClient->msgCtxt; recvLen = ooSocketRecvFrom(pGkClient->rasSocket, recvBuf, 1024, remoteHost, @@ -368,6 +380,7 @@ if(recvLen <0) { OOTRACEERR1("Error:Failed to receive RAS message\n"); + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } OOTRACEDBGA1("GkClient Received RAS Message\n"); @@ -380,6 +393,7 @@ { OOTRACEWARN3("WARN:Ignoring message received from unknown gatekeeper " "%s:%d\n", remoteHost, iFromPort); + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } } @@ -389,6 +403,7 @@ OOTRACEERR1("Error:Failed to set PER buffer for RAS message decoding\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pRasMsg = (H225RasMessage*)memAlloc(pctxt, sizeof(H225RasMessage)); @@ -397,6 +412,7 @@ OOTRACEERR1("Error: Failed to allocate memory for RAS message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } #ifndef _COMPACT @@ -425,8 +441,10 @@ removeEventHandler(pctxt); #endif memReset(pctxt); + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } + ast_mutex_unlock(&pGkClient->Lock); return iRet; } @@ -546,6 +564,7 @@ ASN1OCTET msgBuf[MAXMSGLEN]; ASN1OCTET *msgPtr=NULL; int iLen; + OOCTXT *pctxt = &pGkClient->msgCtxt; setPERBuffer( pctxt, msgBuf, MAXMSGLEN, TRUE ); @@ -600,7 +619,7 @@ OOCTXT *pctxt = &pGkClient->msgCtxt; ooGkClientTimerCb *cbData=NULL; - + ast_mutex_lock(&pGkClient->Lock); /* Allocate memory for RAS message */ pRasMsg = (H225RasMessage*)memAlloc(pctxt, sizeof(H225RasMessage)); @@ -608,6 +627,7 @@ { OOTRACEERR1("Error: Memory allocation for GRQ RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -618,6 +638,7 @@ OOTRACEERR1("Error:Memory allocation for GRQ failed\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memset(pGkReq, 0, sizeof(H225GatekeeperRequest)); @@ -640,6 +661,7 @@ "failed\n"); memReset(&pGkClient->msgCtxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -669,6 +691,7 @@ OOTRACEERR1("Error Failed to fill alias information for GRQ message\n"); memReset(&pGkClient->msgCtxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } iRet = ooGkClientSendMsg(pGkClient, pRasMsg); @@ -677,6 +700,7 @@ OOTRACEERR1("Error: Failed to send GRQ message\n"); memReset(&pGkClient->msgCtxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } OOTRACEINFO1("Sent GRQ message\n"); @@ -686,6 +710,7 @@ { OOTRACEERR1("Error:Failed to allocate memory to GRQ timer callback\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } cbData->timerType = OO_GRQ_TIMER; @@ -697,8 +722,10 @@ OOTRACEERR1("Error:Unable to create GRQ timer.\n "); memFreePtr(&pGkClient->ctxt, cbData); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -858,6 +885,10 @@ H225TransportAddress *pTransportAddress=NULL; H225TransportAddress_ipAddress *pIpAddress=NULL; ooGkClientTimerCb *cbData =NULL; + H225SupportedProtocols *pProtocol = NULL; + H225VoiceCaps *pVoiceCaps = NULL; + + ast_mutex_lock(&pGkClient->Lock); pctxt = &pGkClient->msgCtxt; @@ -866,6 +897,7 @@ { OOTRACEERR1("Error: Memory allocation for RRQ RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -876,6 +908,7 @@ OOTRACEERR1("Error:Memory allocation for RRQ failed\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memset(pRegReq, 0, sizeof(H225RegistrationRequest)); @@ -895,6 +928,7 @@ "RRQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pTransportAddress->t = T_H225TransportAddress_ipAddress; @@ -920,6 +954,7 @@ "RRQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_lock(&pGkClient->Lock); return OO_FAILED; } @@ -943,15 +978,44 @@ pRegReq->terminalType.m.vendorPresent=TRUE; ooGkClientFillVendor(pGkClient, &pRegReq->terminalType.vendor ); - + + if (gH323ep.isGateway) { + pRegReq->terminalType.gateway.m.protocolPresent = TRUE; + pProtocol = (H225SupportedProtocols*) memAlloc(pctxt, + sizeof(H225SupportedProtocols)); + pVoiceCaps = (H225VoiceCaps*) memAlloc(pctxt, sizeof(H225VoiceCaps)); + if(!pProtocol || !pVoiceCaps) { + OOTRACEERR1("Error:Failed to allocate memory for protocol info of " + "RRQ message\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_lock(&pGkClient->Lock); + return OO_FAILED; + } + + memset(pVoiceCaps, 0, sizeof(H225VoiceCaps)); + memset(pProtocol, 0, sizeof(H225SupportedProtocols)); + + pVoiceCaps->m.supportedPrefixesPresent = TRUE; + ooPopulatePrefixList(pctxt, gH323ep.aliases, &pVoiceCaps->supportedPrefixes); + + pProtocol->t = T_H225SupportedProtocols_voice; + pProtocol->u.voice = pVoiceCaps; + + dListInit(&pRegReq->terminalType.gateway.protocol); + dListAppend(pctxt, &pRegReq->terminalType.gateway.protocol, + (void*)pProtocol); + + } + pRegReq->m.terminalAliasPresent=TRUE; if(OO_OK != ooPopulateAliasList(pctxt, gH323ep.aliases, - &pRegReq->terminalAlias)) - { - OOTRACEERR1("Error filling alias for RRQ\n"); - memReset(pctxt); - pGkClient->state = GkClientFailed; - return OO_FAILED; + &pRegReq->terminalAlias)) { + OOTRACEERR1("Error filling alias for RRQ\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; } pRegReq->m.gatekeeperIdentifierPresent=TRUE; @@ -964,6 +1028,7 @@ "message.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy(pRegReq->gatekeeperIdentifier.data, pGkClient->gkId.data, @@ -1008,6 +1073,7 @@ OOTRACEERR1("Error: Failed to allocate memory for EndpointIdentifier in RRQ \n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } } @@ -1021,6 +1087,7 @@ OOTRACEERR1("Error: Failed to send RRQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } OOTRACEINFO1("Sent RRQ message \n"); @@ -1031,6 +1098,7 @@ { OOTRACEERR1("Error:Failed to allocate memory to RRQ timer callback\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } cbData->timerType = OO_RRQ_TIMER; @@ -1042,9 +1110,11 @@ OOTRACEERR1("Error:Unable to create GRQ timer.\n "); memFreePtr(&pGkClient->ctxt, cbData); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -1290,6 +1360,7 @@ H225TransportAddress *pTransportAddress=NULL; H225TransportAddress_ipAddress *pIpAddress=NULL; + ast_mutex_lock(&pGkClient->Lock); pctxt = &pGkClient->msgCtxt; OOTRACEDBGA1("Building Unregistration Request message\n"); @@ -1299,6 +1370,7 @@ { OOTRACEERR1("Error: Memory allocation for URQ RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -1309,6 +1381,7 @@ OOTRACEERR1("Error:Memory allocation for URQ failed\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memset(pUnregReq, 0, sizeof(H225UnregistrationRequest)); @@ -1332,6 +1405,7 @@ "RRQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pTransportAddress->t = T_H225TransportAddress_ipAddress; @@ -1355,6 +1429,7 @@ "message.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pUnregReq->endpointIdentifier.data, @@ -1371,6 +1446,7 @@ OOTRACEERR1("Error:Failed to allocate memory for GKID of URQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pUnregReq->gatekeeperIdentifier.data, @@ -1391,11 +1467,13 @@ OOTRACEERR1("Error:Failed to send UnregistrationRequest message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pGkClient->state = GkClientUnregistered; OOTRACEINFO1("Unregistration Request message sent.\n"); + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -1449,6 +1527,8 @@ H225RasMessage *pRasMsg=NULL; H225UnregistrationConfirm *pUCF=NULL; + ast_mutex_lock(&pGkClient->Lock); + pRasMsg = (H225RasMessage*)memAlloc(pctxt, sizeof(H225RasMessage)); pUCF = (H225UnregistrationConfirm*)memAlloc(pctxt, sizeof(H225UnregistrationConfirm)); @@ -1456,6 +1536,7 @@ { OOTRACEERR1("Error: Memory allocation for UCF RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pRasMsg->t = T_H225RasMessage_unregistrationConfirm; @@ -1470,11 +1551,13 @@ OOTRACEERR1("Error:Failed to send UnregistrationConfirm message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } OOTRACEINFO1("Unregistration Confirm message sent for \n"); memReset(pctxt); + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -1496,6 +1579,8 @@ RasCallAdmissionInfo *pCallAdmInfo=NULL; pctxt = &pGkClient->msgCtxt; + ast_mutex_lock(&pGkClient->Lock); + OOTRACEDBGA3("Building Admission Request for call (%s, %s)\n", call->callType, call->callToken); pRasMsg = (H225RasMessage*)memAlloc(pctxt, sizeof(H225RasMessage)); @@ -1504,6 +1589,7 @@ OOTRACEERR3("Error:Memory - ooGkClientSendAdmissionRequest - " "pRasMsg(%s, %s)\n", call->callType, call->callToken); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pRasMsg->t = T_H225RasMessage_admissionRequest; @@ -1515,6 +1601,7 @@ "pAdmReq(%s, %s)\n", call->callType, call->callToken); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memset(pAdmReq, 0, sizeof(H225AdmissionRequest)); @@ -1533,6 +1620,7 @@ "Addresses of ARQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddressLocal->ip.data); @@ -1597,6 +1685,7 @@ call->callToken); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pAdmReq->endpointIdentifier.data, @@ -1633,6 +1722,7 @@ "ARQ message\n"); pGkClient->state = GkClientFailed; memReset(pctxt); + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } } @@ -1646,7 +1736,8 @@ { OOTRACEERR1("Error:Failed to populate source aliases -ARQ message\n"); memReset(pctxt); - pGkClient->state = GkClientFailed; + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } } @@ -1684,6 +1775,7 @@ OOTRACEERR1("Error:Failed to allocate memory for GKID of ARQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pAdmReq->gatekeeperIdentifier.data, @@ -1704,6 +1796,7 @@ " Info entry\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -1731,6 +1824,7 @@ OOTRACEERR1("Error:Failed to send AdmissionRequest message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } OOTRACEINFO3("Admission Request message sent for (%s, %s)\n", @@ -1745,6 +1839,7 @@ OOTRACEERR1("Error:Failed to allocate memory for Regisration timer." "\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } cbData->timerType = OO_ARQ_TIMER; @@ -1757,9 +1852,11 @@ OOTRACEERR1("Error:Unable to create ARQ timer.\n "); memFreePtr(&pGkClient->ctxt, cbData); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } @@ -1850,8 +1947,12 @@ } OOTRACEINFO3("Admission Confirm message received for (%s, %s)\n", pCallAdmInfo->call->callType, - pCallAdmInfo->call->callToken); - ooH323CallAdmitted( pCallAdmInfo->call); + pCallAdmInfo->call->callToken); + + pCallAdmInfo->call->callState = OO_CALL_CONNECTING; + ast_cond_broadcast(&pCallAdmInfo->call->gkWait); + /* ooH323CallAdmitted( pCallAdmInfo->call); */ + dListRemove(&pGkClient->callsPendingList, pNode); dListAppend(&pGkClient->ctxt, &pGkClient->callsAdmittedList, pNode->data); @@ -1948,9 +2049,272 @@ break; } + ast_cond_broadcast(&pCallAdmInfo->call->gkWait); return OO_OK; } + +int ooGkClientSendIRR + (ooGkClient *pGkClient, OOH323CallData *call) +{ + int iRet = 0; + unsigned int x; + DListNode *pNode; + ooGkClientTimerCb *cbData=NULL; + H225RasMessage *pRasMsg=NULL; + OOCTXT* pctxt; + H225InfoRequestResponse *pIRR=NULL; + H225TransportAddress_ipAddress *pIpAddressLocal =NULL, *pIpRasAddress, + *pLocalAddr, *pRemoteAddr; + H225TransportAddress *pTransportAddress; + ooAliases *destAliases = NULL, *srcAliases=NULL; + H225InfoRequestResponse_perCallInfo_element *perCallInfo = NULL; + pctxt = &pGkClient->msgCtxt; + + ast_mutex_lock(&pGkClient->Lock); + + OOTRACEDBGA3("Building Info Request Resp for call (%s, %s)\n", + call->callType, call->callToken); + pRasMsg = (H225RasMessage*)memAlloc(pctxt, sizeof(H225RasMessage)); + if(!pRasMsg) + { + OOTRACEERR3("Error:Memory - ooGkClientSendAdmissionRequest - " + "pRasMsg(%s, %s)\n", call->callType, call->callToken); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + pRasMsg->t = T_H225RasMessage_infoRequestResponse; + pIRR = (H225InfoRequestResponse*) memAlloc(pctxt, + sizeof(H225InfoRequestResponse)); + if(!pIRR) + { + OOTRACEERR3("Error:Memory - ooGkClientSendIRR - " + "pIRR(%s, %s)\n", call->callType, call->callToken); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + memset(pIRR, 0, sizeof(H225InfoRequestResponse)); + pRasMsg->u.infoRequestResponse = pIRR; + + /* Populate call signalling addresses */ + pIpAddressLocal = (H225TransportAddress_ipAddress*)memAlloc(pctxt, + sizeof(H225TransportAddress_ipAddress)); + pTransportAddress = (H225TransportAddress*) memAlloc(pctxt, + sizeof(H225TransportAddress)); + if(!pIpAddressLocal || !pTransportAddress) + { + OOTRACEERR1("Error:Failed to allocate memory for Call Signalling " + "Addresses of IRR message\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddressLocal->ip.data); + + pIpAddressLocal->ip.numocts = 4; + pIpAddressLocal->port = gH323ep.listenPort; + + pTransportAddress->t = T_H225TransportAddress_ipAddress; + pTransportAddress->u.ipAddress = pIpAddressLocal; + + dListInit(&pIRR->callSignalAddress); + dListAppend(pctxt, &pIRR->callSignalAddress, + (void*)pTransportAddress); + + /* Populate seq number */ + pIRR->requestSeqNum = pGkClient->requestSeqNum++; + if(!pIRR->requestSeqNum) + pIRR->requestSeqNum = pGkClient->requestSeqNum++; + + pIpRasAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt, + sizeof(H225TransportAddress_ipAddress)); + if(!pIpRasAddress) + { + OOTRACEERR1("Error: Memory allocation for Ras Address of IRR message " + "failed\n"); + memReset(&pGkClient->msgCtxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + + pIpRasAddress->ip.numocts = 4; + pIpRasAddress->port = pGkClient->localRASPort; + ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpRasAddress->ip.data); + + pIRR->rasAddress.u.ipAddress = pIpRasAddress; + pIRR->rasAddress.t=T_H225TransportAddress_ipAddress; /* IPv4 address */ + + /* Pose as gateway or terminal as per config */ + if(gH323ep.isGateway) + pIRR->endpointType.m.gatewayPresent = TRUE; + else + pIRR->endpointType.m.terminalPresent = TRUE; + + pIRR->endpointType.m.nonStandardDataPresent=FALSE; + pIRR->endpointType.m.vendorPresent=TRUE; + ooGkClientFillVendor(pGkClient, &pIRR->endpointType.vendor); + + /* Populate Endpoint Identifier */ + pIRR->endpointIdentifier.nchars = pGkClient->endpointId.nchars; + pIRR->endpointIdentifier.data = (ASN116BITCHAR*)memAlloc(pctxt, + sizeof(ASN116BITCHAR)*pGkClient->endpointId.nchars); + if(!pIRR->endpointIdentifier.data) + { + OOTRACEERR3("Error:Memory - ooGkClientSendIRR - " + "endpointIdentifier.data(%s, %s)\n", call->callType, + call->callToken); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + memcpy((void*)pIRR->endpointIdentifier.data, + (void*)pGkClient->endpointId.data, + sizeof(ASN116BITCHAR)*pGkClient->endpointId.nchars); + + + /* Populate call aliases */ + if(call->ourAliases) + srcAliases = call->ourAliases; + else + srcAliases = gH323ep.aliases; + + /* Populate Source Info */ + if(srcAliases) + { + iRet = ooPopulateAliasList(&pGkClient->msgCtxt, srcAliases, + &pIRR->endpointAlias); + if(OO_OK != iRet) + { + OOTRACEERR1("Error:Failed to populate source aliases -ARQ message\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + } + pIRR->m.endpointAliasPresent = TRUE; + + /* Populate need response & unsolicited */ + pIRR->needResponse = FALSE; + pIRR->m.needResponsePresent = TRUE; + pIRR->unsolicited = TRUE; + pIRR->m.unsolicitedPresent = TRUE; + + /* Populate perCallInfo */ + + pIRR->m.perCallInfoPresent = TRUE; + + perCallInfo = + (H225InfoRequestResponse_perCallInfo_element *)memAlloc(pctxt, + sizeof(H225InfoRequestResponse_perCallInfo_element)); + memset(perCallInfo, 0, sizeof(H225InfoRequestResponse_perCallInfo_element)); + + if(!perCallInfo) + { + OOTRACEERR3("Error:Memory - ooGkClientSendIRR - " + "perCallInfo for (%s, %s)\n", call->callType, + call->callToken); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + + perCallInfo->m.originatorPresent = TRUE; + perCallInfo->originator = (!strcmp(call->callType, "incoming")) ? FALSE : TRUE; + + pLocalAddr = (H225TransportAddress_ipAddress*)memAlloc(pctxt, + sizeof(H225TransportAddress_ipAddress)); + pRemoteAddr = (H225TransportAddress_ipAddress*) memAlloc(pctxt, + sizeof(H225TransportAddress_ipAddress)); + if(!pLocalAddr || !pRemoteAddr) + { + OOTRACEERR1("Error:Failed to allocate memory for Call Signalling " + "Addresses of IRR message\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + pLocalAddr->ip.numocts = 4; + ooSocketConvertIpToNwAddr(call->localIP, pLocalAddr->ip.data); + pLocalAddr->port = (call->pH225Channel->port) ? call->pH225Channel->port : gH323ep.listenPort; + + pRemoteAddr->ip.numocts = 4; + ooSocketConvertIpToNwAddr(call->remoteIP, pRemoteAddr->ip.data); + pRemoteAddr->port = call->remotePort; + + perCallInfo->callSignaling.m.sendAddressPresent = TRUE; + perCallInfo->callSignaling.sendAddress.t = T_H225TransportAddress_ipAddress; + perCallInfo->callSignaling.m.recvAddressPresent = TRUE; + perCallInfo->callSignaling.recvAddress.t = T_H225TransportAddress_ipAddress; + + if (!strcmp(call->callType, "incoming")) { +// terminator + perCallInfo->callSignaling.sendAddress.u.ipAddress = pRemoteAddr; + perCallInfo->callSignaling.recvAddress.u.ipAddress = pLocalAddr; + } else { +// originator + perCallInfo->callSignaling.sendAddress.u.ipAddress = pLocalAddr; + perCallInfo->callSignaling.recvAddress.u.ipAddress = pRemoteAddr; + } + + /* Populate call Reference */ + perCallInfo->callReferenceValue = call->callReference; + /* populate conferenceID */ + memcpy((void*)&perCallInfo->conferenceID, (void*)&call->confIdentifier, + sizeof(H225ConferenceIdentifier)); + /* Populate call identifier */ + perCallInfo->m.callIdentifierPresent = TRUE; + memcpy((void*)&perCallInfo->callIdentifier, (void*)&call->callIdentifier, + sizeof(H225CallIdentifier)); + /* Populate call type & call model */ + perCallInfo->callType.t = T_H225CallType_pointToPoint; + /* Add call model to message*/ + if(OO_TESTFLAG(call->flags, OO_M_GKROUTED)) + perCallInfo->callModel.t = T_H225CallModel_gatekeeperRouted; + else + perCallInfo->callModel.t = T_H225CallModel_direct; + + /* Populate usage info */ + if (call->alertingTime) { + perCallInfo->usageInformation.m.alertingTimePresent = TRUE; + perCallInfo->usageInformation.alertingTime = call->alertingTime; + } + if (call->connectTime) { + perCallInfo->usageInformation.m.connectTimePresent = TRUE; + perCallInfo->usageInformation.connectTime = call->connectTime; + } + perCallInfo->usageInformation.m.endTimePresent = FALSE; + perCallInfo->m.usageInformationPresent = TRUE; + + dListInit(&pIRR->perCallInfo); + dListAppend(pctxt, &pIRR->perCallInfo, + (void*)perCallInfo); + + iRet = ooGkClientSendMsg(pGkClient, pRasMsg); + if(iRet != OO_OK) + { + OOTRACEERR1("Error:Failed to send IRR message\n"); + memReset(pctxt); + pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); + return OO_FAILED; + } + OOTRACEINFO3("IRR message sent for (%s, %s)\n", + call->callType, call->callToken); + memReset(pctxt); + + ast_mutex_unlock(&pGkClient->Lock); + return OO_OK; +} + /** * This function is invoked to request call disengage to gatekeeper. * @@ -1970,6 +2334,8 @@ RasCallAdmissionInfo* pCallAdmInfo=NULL; pctxt = &pGkClient->msgCtxt; + ast_mutex_lock(&pGkClient->Lock); + OOTRACEINFO3("Sending disengage Request for call. (%s, %s)\n", call->callType, call->callToken); @@ -1978,6 +2344,7 @@ { OOTRACEERR1("Error: Memory allocation for DRQ RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -1989,6 +2356,7 @@ OOTRACEERR1("Error: Failed to allocate memory for DRQ message\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -2009,6 +2377,7 @@ "message.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pDRQ->endpointIdentifier.data, @@ -2040,6 +2409,7 @@ OOTRACEERR1("Error:Failed to allocate memory for GKId in DRQ.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy(pDRQ->gatekeeperIdentifier.data, pGkClient->gkId.data, @@ -2055,12 +2425,31 @@ OOTRACEERR1("Error: Failed to allocate memory for cause ie in DRQ.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } pDRQ->terminationCause.u.releaseCompleteCauseIE->numocts = strlen("Call Ended"); strcpy(pDRQ->terminationCause.u.releaseCompleteCauseIE->data, "Call Ended"); + /* populate usage info */ + + /* Populate usage info */ + if (call->alertingTime) { + pDRQ->usageInformation.m.alertingTimePresent = TRUE; + pDRQ->usageInformation.alertingTime = call->alertingTime; + } + if (call->connectTime) { + pDRQ->usageInformation.m.connectTimePresent = TRUE; + pDRQ->usageInformation.connectTime = call->connectTime; + } + pDRQ->usageInformation.m.endTimePresent = TRUE; + if (call->endTime) + pDRQ->usageInformation.endTime = call->endTime; + else + pDRQ->usageInformation.endTime = time(NULL); + pDRQ->m.usageInformationPresent = TRUE; + iRet = ooGkClientSendMsg(pGkClient, pRasMsg); if(iRet != OO_OK) { @@ -2083,6 +2472,7 @@ break; } } + ast_mutex_unlock(&pGkClient->Lock); return iRet; } @@ -2199,6 +2589,8 @@ ooGkClientTimerCb *cbData=NULL; RasCallAdmissionInfo *pAdmInfo = NULL; + ast_mutex_lock(&pGkClient->Lock); + for(x=0; xcallsAdmittedList.count; x++) { @@ -2209,7 +2601,7 @@ dListRemove(&pGkClient->callsAdmittedList, pNode); memFreePtr(&pGkClient->ctxt, pAdmInfo); memFreePtr(&pGkClient->ctxt, pNode); - return OO_OK; + break; } } @@ -2237,10 +2629,11 @@ dListRemove(&pGkClient->callsPendingList, pNode); memFreePtr(&pGkClient->ctxt, pAdmInfo); memFreePtr(&pGkClient->ctxt, pNode); - return OO_OK; + break; } } + ast_mutex_unlock(&pGkClient->Lock); return OO_OK; } --- ./channels/ooh323c/src/memheap.h 2008-02-07 23:59:47.000000000 +0300 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/memheap.h 2009-05-30 06:40:48.000000000 +0400 @@ -50,6 +50,7 @@ ASN1UINT defBlkSize; ASN1UINT refCnt; ASN1UINT flags; + ast_mutex_t pLock; } OSMemHeap; /* see rtMemDefs.c file */ --- ./channels/ooh323c/src/ooCapability.c 2008-06-04 21:35:29.000000000 +0400 +++ ../../asterisk-addons-1.6.1.0/./channels/ooh323c/src/ooCapability.c 2009-07-29 00:21:44.000000000 +0400 @@ -13,6 +13,9 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include + #include "ooCapability.h" #include "ootrace.h" #include "ooCalls.h" @@ -335,8 +338,7 @@ if(!call->ourCaps){ call->ourCaps = epCap; ooResetCapPrefs(call); - } - else{ + }else{ cur = call->ourCaps; while(cur->next) cur = cur->next; cur->next = epCap; @@ -449,6 +451,19 @@ return OO_OK; } +int epCapIsPreferred(OOH323CallData *call, ooH323EpCapability *epCap) +{ + ooH323EpCapability *curCap = call->ourCaps; + while (curCap) { + if (curCap->capType == epCap->capType) { + if (curCap->cap == epCap->cap) + return 1; + else + return 0; + } + curCap = curCap->next; + } +} int ooCapabilityAddGSMCapability(OOH323CallData *call, int cap, unsigned framesPerPkt, OOBOOL comfortNoise, @@ -544,6 +559,100 @@ return OO_OK; } +/* Used for T38 */ +int ooCapabilityAddT38Capability + (OOH323CallData *call, int cap, int dir, + cb_StartReceiveChannel startReceiveChannel, + cb_StartTransmitChannel startTransmitChannel, + cb_StopReceiveChannel stopReceiveChannel, + cb_StopTransmitChannel stopTransmitChannel, + OOBOOL remote) +{ + ooH323EpCapability *epCap = NULL, *cur=NULL; + OOCapParams *params=NULL; + OOCTXT *pctxt=NULL; + if(!call) pctxt = &gH323ep.ctxt; + else pctxt = call->pctxt; + + epCap = (ooH323EpCapability*)memAllocZ(pctxt, sizeof(ooH323EpCapability)); + params = (OOCapParams*) memAlloc(pctxt, sizeof(OOCapParams)); + memset(params, 0 , sizeof(OOCapParams)); + if(!epCap || !params) + { + OOTRACEERR1("ERROR: Memory - ooCapabilityAddT38Capability - " + "epCap/params\n"); + return OO_FAILED; + } + + if(dir & OORXANDTX) { + epCap->dir = OORX; + epCap->dir |= OOTX; + } + else { + epCap->dir = dir; + } + + epCap->cap = cap; + epCap->capType = OO_CAP_TYPE_DATA; + epCap->params = (void*)params; + epCap->startReceiveChannel = startReceiveChannel; + epCap->startTransmitChannel = startTransmitChannel; + epCap->stopReceiveChannel = stopReceiveChannel; + epCap->stopTransmitChannel = stopTransmitChannel; + epCap->next = NULL; + + if(!call) + { + /* Add as local capability */ + OOTRACEDBGC2("Adding endpoint capability %s. \n", + ooGetCapTypeText(epCap->cap)); + if(!gH323ep.myCaps) { + gH323ep.myCaps = epCap; + } + else{ + cur = gH323ep.myCaps; + while(cur->next) cur = cur->next; + cur->next = epCap; + } + ooAppendCapToCapPrefs(NULL, cap); + gH323ep.noOfCaps++; + } + else{ + if(remote) + { + /* Add as remote capability */ + if(!call->remoteCaps) { + call->remoteCaps = epCap; + } + else{ + cur = call->remoteCaps; + while(cur->next) cur = cur->next; + cur->next = epCap; + } + call->t38sides |= 2; + } + else{ + /* Add as our capability */ + OOTRACEDBGC4("Adding call specific capability %s. (%s, %s)\n", + ooGetCapTypeText(epCap->cap), call->callType, + call->callToken); + if(!call->ourCaps){ + call->ourCaps = epCap; + ooResetCapPrefs(call); + } + else{ + cur = call->ourCaps; + while(cur->next) cur = cur->next; + cur->next = epCap; + } + ooAppendCapToCapPrefs(call, cap); + call->t38sides |= 1; + } + } + + return OO_OK; +} + @@ -609,12 +718,18 @@ case OO_G711ALAW56K: case OO_G711ULAW64K: case OO_G711ULAW56K: - /*case OO_G726:*/ case OO_G728: case OO_G729: case OO_G729A: + case OO_G729B: case OO_G7231: return ooCapabilityCreateSimpleCapability(epCap, pctxt, dir); + case OO_G726: + case OO_G726AAL2: + case OO_AMRNB: + return ooCapabilityCreateNonStandardCapability(epCap, pctxt, dir); + case OO_GSMHALFRATE: + case OO_GSMENHANCEDFULLRATE: case OO_GSMFULLRATE: return ooCapabilityCreateGSMFullRateCapability(epCap, pctxt, dir); default: @@ -644,6 +759,7 @@ memset(pATECap, 0, sizeof(H245AudioTelephonyEventCapability)); pATECap->dynamicRTPPayloadType = giDynamicRTPPayloadType; events = (char*)memAlloc(pctxt, strlen("0-16")+1); + memset(events, 0, strlen("0-16")+1); if(!events) { OOTRACEERR1("Error:Memory - ooCapabilityCreateDTMFCapability - events\n"); @@ -774,8 +890,16 @@ "pAudio/pGSMCap\n"); return NULL; } - - pAudio->t = T_H245AudioCapability_gsmFullRate; + switch (epCap->cap) { + case OO_GSMHALFRATE: + pAudio->t = T_H245AudioCapability_gsmHalfRate; + break; + case OO_GSMENHANCEDFULLRATE: + pAudio->t = T_H245AudioCapability_gsmEnhancedFullRate; + break; + default: + pAudio->t = T_H245AudioCapability_gsmFullRate; + } pAudio->u.gsmFullRate = pGSMCap; if(dir & OORX) pGSMCap->audioUnitSize = ((OOGSMCapParams*)epCap->params)->rxframes*OO_GSMFRAMESIZE; @@ -840,13 +964,6 @@ else pAudio->u.g711Ulaw64k = params->txframes; return pAudio; - /*case OO_G726: - pAudio->t = T_H245AudioCapability_g726; - if(dir & OORX) - pAudio->u.g726 = params->rxframes; - else - pAudio->u.g726 = params->txframes; - return pAudio;*/ case OO_G728: pAudio->t = T_H245AudioCapability_g728; if(dir & OORX) @@ -868,6 +985,13 @@ else pAudio->u.g729AnnexA = params->txframes; return pAudio; + case OO_G729B: + pAudio->t = T_H245AudioCapability_g729wAnnexB; + if(dir & OORX) + pAudio->u.g729AnnexA = params->rxframes; + else + pAudio->u.g729AnnexA = params->txframes; + return pAudio; case OO_G7231: pAudio->t = T_H245AudioCapability_g7231; pAudio->u.g7231 = (H245AudioCapability_g7231*)memAlloc(pctxt, @@ -891,6 +1015,159 @@ } return NULL; } +/* This is used for g726, AMRNB */ +struct H245AudioCapability* ooCapabilityCreateNonStandardCapability + (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir) +{ + H245AudioCapability *pAudio=NULL; + OOCapParams *params; + if(!epCap || !epCap->params) + { + OOTRACEERR1("Error:Invalid capability parameters to " + "ooCapabilityCreateSimpleCapability.\n"); + return NULL; + } + params =(OOCapParams*)epCap->params; + pAudio = (H245AudioCapability*)memAlloc(pctxt, + sizeof(H245AudioCapability)); + if(!pAudio) + { + OOTRACEERR1("ERROR:Memory - ooCapabilityCreateSimpleCapability - pAudio\n"); + return NULL; + } + + + switch(epCap->cap) + { + case OO_AMRNB: + case OO_G726: + case OO_G726AAL2: + pAudio->t = T_H245AudioCapability_nonStandard; + pAudio->u.nonStandard = (H245NonStandardParameter*)memAlloc(pctxt, + sizeof(H245NonStandardParameter)); + if(!pAudio->u.nonStandard) + { + OOTRACEERR1("Error:Memory - ooCapabilityCreateSimpleCapability - g726\n"); + memFreePtr(pctxt, pAudio); + return NULL; + } + + pAudio->u.nonStandard->nonStandardIdentifier.t=T_H245NonStandardIdentifier_h221NonStandard; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard = + (H245NonStandardIdentifier_h221NonStandard *) memAlloc(pctxt, + sizeof(H245NonStandardIdentifier_h221NonStandard)); + if (!pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard) { + OOTRACEERR2("Error:Memory - ooCapabilityCreateSimpleCapability - %d\n", epCap->cap); + memFreePtr(pctxt, pAudio); + return NULL; + } + + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35CountryCode = + gH323ep.t35CountryCode; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35Extension = + gH323ep.t35Extension; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->manufacturerCode = + gH323ep.manufacturerCode; + + switch (epCap->cap) { + case OO_G726: + pAudio->u.nonStandard->data.data = "G.726-32k"; + pAudio->u.nonStandard->data.numocts = sizeof("G.726-32k")-1; + break; + case OO_G726AAL2: + pAudio->u.nonStandard->data.data = "G726r32"; + pAudio->u.nonStandard->data.numocts = sizeof("G726r32")-1; + /* Cisco G726 */ + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35CountryCode = 181; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35Extension = 0; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->manufacturerCode = 18; + + break; + case OO_AMRNB: + pAudio->u.nonStandard->data.data = "AMRNB"; + pAudio->u.nonStandard->data.numocts = sizeof("AMRNB")-1; + } + return pAudio; + + default: + OOTRACEERR2("ERROR: Don't know how to create audio capability %d\n", + epCap->cap); + } + return NULL; +} + +/* Our t.38 params */ + +struct H245DataApplicationCapability_application* ooCreateT38ApplicationData + (OOCTXT* pctxt, H245DataApplicationCapability_application *app) +{ + app->t = T_H245DataApplicationCapability_application_t38fax; + app->u.t38fax = + (H245DataApplicationCapability_application_t38fax *) memAlloc(pctxt, + sizeof(H245DataApplicationCapability_application_t38fax)); + if (!app->u.t38fax) { + OOTRACEERR1("Error:Memory - ooCreateT38AppData\n"); + return NULL; + } + memset(app->u.t38fax, 0, sizeof(H245DataApplicationCapability_application_t38fax)); + app->u.t38fax->t38FaxProtocol.t = T_H245DataProtocolCapability_udp; + app->u.t38fax->t38FaxProfile.m.versionPresent = TRUE; + app->u.t38fax->t38FaxProfile.version = 0; + app->u.t38fax->t38FaxProfile.m.t38FaxRateManagementPresent = TRUE; + app->u.t38fax->t38FaxProfile.t38FaxRateManagement.t = + T_H245T38FaxRateManagement_transferredTCF; + app->u.t38fax->t38FaxProfile.m.t38FaxUdpOptionsPresent = TRUE; + app->u.t38fax->t38FaxProfile.t38FaxUdpOptions.m.t38FaxMaxBufferPresent = TRUE; + app->u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxMaxBuffer = 200; + app->u.t38fax->t38FaxProfile.t38FaxUdpOptions.m.t38FaxMaxDatagramPresent = TRUE; + app->u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxMaxDatagram = 72; + app->u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxUdpEC.t = + T_H245T38FaxUdpOptions_t38FaxUdpEC_t38UDPRedundancy; + + return app; +} + +/* This is used for T.38 */ +struct H245DataApplicationCapability* ooCapabilityCreateT38Capability + (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir) +{ + H245DataApplicationCapability *pT38=NULL; + OOCapParams *params; + if(!epCap || !epCap->params) + { + OOTRACEERR1("Error:Invalid capability parameters to " + "ooCapabilityCreateSimpleCapability.\n"); + return NULL; + } + params =(OOCapParams*)epCap->params; + pT38 = (H245DataApplicationCapability*)memAlloc(pctxt, + sizeof(H245DataApplicationCapability)); + if(!pT38) + { + OOTRACEERR1("ERROR:Memory - ooCapabilityCreateT38Capability - pT38\n"); + return NULL; + } + memset(pT38, 0, sizeof(H245DataApplicationCapability)); + + + switch(epCap->cap) + { + case OO_T38: + pT38->maxBitRate = 144; + if (!ooCreateT38ApplicationData(pctxt,&(pT38->application))) { + OOTRACEERR2("Error:Memory - ooCapabilityCreateT38Capability - %d\n", epCap->cap); + memFreePtr(pctxt, pT38); + return NULL; + } + return pT38; + + default: + OOTRACEERR2("ERROR: Don't know how to create T38 capability %d\n", + epCap->cap); + } + return NULL; +} + /* Used for g711 ulaw/alaw, g728, g729, g729a, g7231 */ ASN1BOOL ooCapabilityCheckCompatibility_Simple @@ -935,10 +1212,15 @@ cap = OO_G729A; noofframes = audioCap->u.g729AnnexA; break; + case T_H245AudioCapability_g729wAnnexB: + cap = OO_G729B; + noofframes = audioCap->u.g729wAnnexB; + break; case T_H245AudioCapability_g7231: cap = OO_G7231; noofframes = audioCap->u.g7231->maxAl_sduAudioFrames; break; + default: return FALSE; } @@ -978,6 +1260,54 @@ return FALSE; } +/* Used for g726, AMRNB */ +ASN1BOOL ooCapabilityCheckCompatibility_NonStandard + (OOH323CallData *call, ooH323EpCapability* epCap, + H245AudioCapability* audioCap, int dir) +{ + int noofframes=0, cap; + + OOTRACEDBGC2("Comparing channel with codec type: %d\n", audioCap->t); + + if (audioCap->t == T_H245AudioCapability_nonStandard && + audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard) { + switch (audioCap->u.nonStandard->data.numocts) { + case sizeof("G.726-32k")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "G.726-32k", + audioCap->u.nonStandard->data.numocts)) + cap = OO_G726; + else + return FALSE; + break; + case sizeof("G726r32")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "G726r32", + audioCap->u.nonStandard->data.numocts)) + cap = OO_G726AAL2; + else + return FALSE; + break; + case sizeof("AMRNB")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "AMRNB", + audioCap->u.nonStandard->data.numocts)) + cap = OO_AMRNB; + else + return FALSE; + break; + default: + return FALSE; + } + } else + return FALSE; + + OOTRACEDBGC3("Comparing codecs: current=%d, requested=%d\n", + epCap->cap, cap); + if(cap != epCap->cap) { return FALSE; } + + return TRUE; + +} OOBOOL ooCapabilityCheckCompatibility_GSM @@ -1003,6 +1333,8 @@ return FALSE; } + if(cap != epCap->cap) { return FALSE; } + /* can we receive this capability */ if(dir & OORX) { @@ -1026,6 +1358,25 @@ } +OOBOOL ooCapabilityCheckCompatibility_T38 + (OOH323CallData *call, ooH323EpCapability* epCap, + H245DataApplicationCapability* t38Cap, int dir) +{ + unsigned cap = 0; + switch(t38Cap->application.t) + { + case T_H245DataApplicationCapability_application_t38fax: + cap = OO_T38; + break; + default: + return FALSE; + } + + if(cap != epCap->cap) { return FALSE; } + + return TRUE; +} + OOBOOL ooCapabilityCheckCompatibility_H263Video (struct OOH323CallData *call, ooH323EpCapability *epCap, @@ -1202,8 +1553,13 @@ case T_H245AudioCapability_g728: case T_H245AudioCapability_g729: case T_H245AudioCapability_g729AnnexA: + case T_H245AudioCapability_g729wAnnexB: case T_H245AudioCapability_g7231: return ooCapabilityCheckCompatibility_Simple(call, epCap, audioCap, dir); + case T_H245AudioCapability_nonStandard: + return ooCapabilityCheckCompatibility_NonStandard(call, epCap, audioCap, dir); + case T_H245AudioCapability_gsmHalfRate: + case T_H245AudioCapability_gsmEnhancedFullRate: case T_H245AudioCapability_gsmFullRate: return ooCapabilityCheckCompatibility_GSM(call, epCap, audioCap, dir); default: @@ -1224,7 +1580,7 @@ videoCap, dir); default: OOTRACEDBGC3("ooCapabilityCheckCompatibility_Video - Unsupported video " - "capability. (%s, %s)\n", call->callType, call->callToken); + "capability. (%s, $s)\n", call->callType, call->callToken); } return FALSE; } @@ -1249,9 +1605,11 @@ dataType->u.videoData, dir); break; case T_H245DataType_data: + if(epCap->capType == OO_CAP_TYPE_DATA) + return ooCapabilityCheckCompatibility_T38(call, epCap, dataType->u.data, dir); default: OOTRACEDBGC3("ooCapabilityCheckCompatibility - Unsupported " - "capability. (%s, %s)\n", call->callType, call->callToken); + "capability. (%s, $s)\n", call->callType, call->callToken); } return FALSE; @@ -1280,10 +1638,10 @@ case OO_G711ALAW56K: case OO_G711ULAW64K: case OO_G711ULAW56K: - /*case OO_G726:*/ case OO_G728: case OO_G729: case OO_G729A: + case OO_G729B: case OO_G7231: if(((OOCapParams*)txCap->params)->txframes <= ((OOCapParams*)rxCap->params)->rxframes) @@ -1485,10 +1843,15 @@ framesPerPkt = audioCap->u.g729AnnexA; cap = OO_G729A; break; + case T_H245AudioCapability_g729wAnnexB: + framesPerPkt = audioCap->u.g729wAnnexB; + cap = OO_G729B; + break; case T_H245AudioCapability_g7231: framesPerPkt = audioCap->u.g7231->maxAl_sduAudioFrames; cap = OO_G7231; break; + default: return NULL; } @@ -1601,6 +1964,142 @@ return NULL; } +/* used for g726, AMRNB */ +ooH323EpCapability* ooIsAudioDataTypeNonStandardSupported + (OOH323CallData *call, H245AudioCapability* audioCap, int dir) +{ + int cap; + ooH323EpCapability *cur=NULL, *epCap=NULL; + OOCapParams * params= NULL; + + if (audioCap->t == T_H245AudioCapability_nonStandard && + audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard) { + switch (audioCap->u.nonStandard->data.numocts) { + case sizeof("G.726-32k")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "G.726-32k", + audioCap->u.nonStandard->data.numocts)) + cap = OO_G726; + else + return NULL; + break; + case sizeof("G726r32")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "G726r32", + audioCap->u.nonStandard->data.numocts)) + cap = OO_G726AAL2; + else + return NULL; + break; + case sizeof("AMRNB")-1: + if (!strncmp(audioCap->u.nonStandard->data.data, "AMRNB", + audioCap->u.nonStandard->data.numocts)) + cap = OO_AMRNB; + else + return NULL; + break; + default: + return NULL; + } + } else + return NULL; + + OOTRACEDBGC4("Determined Simple audio data type to be of type %s. Searching" + " for matching capability.(%s, %s)\n", + ooGetCapTypeText(cap), call->callType, call->callToken); + + /* If we have call specific caps, we use them; otherwise use general + endpoint caps + */ + if(call->ourCaps) + cur = call->ourCaps; + else + cur = gH323ep.myCaps; + + while(cur) + { + OOTRACEDBGC4("Local cap being compared %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap),call->callType, call->callToken); + + if(cur->cap == cap && (cur->dir & dir)) + break; + cur = cur->next; + } + + if(!cur) return NULL; + + OOTRACEDBGC4("Found matching simple audio capability type %s. Comparing" + " other parameters. (%s, %s)\n", ooGetCapTypeText(cap), + call->callType, call->callToken); + + /* can we receive this capability */ + if(dir & OORX) + { + OOTRACEDBGC4("We can receive Simple capability %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + epCap = (ooH323EpCapability*)memAlloc(call->pctxt, + sizeof(ooH323EpCapability)); + params=(OOCapParams*)memAlloc(call->pctxt,sizeof(OOCapParams)); + if(!epCap || !params) + { + OOTRACEERR3("Error:Memory - ooIsAudioDataTypeSimpleSupported - " + "epCap/params (%s, %s)\n", call->callType, + call->callToken); + return NULL; + } + epCap->params = params; + epCap->cap = cur->cap; + epCap->dir = cur->dir; + epCap->capType = cur->capType; + epCap->startReceiveChannel = cur->startReceiveChannel; + epCap->startTransmitChannel= cur->startTransmitChannel; + epCap->stopReceiveChannel = cur->stopReceiveChannel; + epCap->stopTransmitChannel = cur->stopTransmitChannel; + epCap->next = NULL; + memcpy(epCap->params, cur->params, sizeof(OOCapParams)); + OOTRACEDBGC4("Returning copy of matched receive capability %s. " + "(%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + return epCap; + } + + /* Can we transmit compatible stream */ + if(dir & OOTX) + { + OOTRACEDBGC4("We can transmit Simple capability %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + epCap = (ooH323EpCapability*)memAlloc(call->pctxt, + sizeof(ooH323EpCapability)); + params =(OOCapParams*)memAlloc(call->pctxt,sizeof(OOCapParams)); + if(!epCap || !params) + { + OOTRACEERR3("Error:Memory - ooIsAudioDataTypeSimpleSupported - " + "epCap/params (%s, %s)\n", call->callType, + call->callToken); + return NULL; + } + epCap->params = params; + epCap->cap = cur->cap; + epCap->dir = cur->dir; + epCap->capType = cur->capType; + epCap->startReceiveChannel = cur->startReceiveChannel; + epCap->startTransmitChannel= cur->startTransmitChannel; + epCap->stopReceiveChannel = cur->stopReceiveChannel; + epCap->stopTransmitChannel = cur->stopTransmitChannel; + epCap->next = NULL; + memcpy(epCap->params, cur->params, sizeof(OOCapParams)); + OOTRACEDBGC4("Returning copy of matched transmit capability %s." + "(%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + return epCap; + } + return NULL; +} + ooH323EpCapability* ooIsAudioDataTypeSupported @@ -1617,8 +2116,11 @@ case T_H245AudioCapability_g728: case T_H245AudioCapability_g729: case T_H245AudioCapability_g729AnnexA: + case T_H245AudioCapability_g729wAnnexB: case T_H245AudioCapability_g7231: return ooIsAudioDataTypeSimpleSupported(call, audioCap, dir); + case T_H245AudioCapability_nonStandard: + return ooIsAudioDataTypeNonStandardSupported(call, audioCap, dir); case T_H245AudioCapability_gsmFullRate: case T_H245AudioCapability_gsmHalfRate: case T_H245AudioCapability_gsmEnhancedFullRate: @@ -1628,6 +2130,110 @@ } } +ooH323EpCapability* ooIsT38Supported + (OOH323CallData *call, H245DataApplicationCapability* t38Cap, int dir) +{ + int cap = 0; + ooH323EpCapability *cur=NULL, *epCap=NULL; + OOCapParams *params= NULL; + /* Find similar capability */ + switch(t38Cap->application.t) + { + case T_H245DataApplicationCapability_application_t38fax: + cap = OO_T38; + break; + default: + return NULL; + } + + if(call->ourCaps) + cur = call->ourCaps; + else + cur = gH323ep.myCaps; + + while(cur) + { + OOTRACEDBGC4("Local cap being compared %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap),call->callType, call->callToken); + + if(cur->cap == cap && (cur->dir & dir)) + break; + cur = cur->next; + } + + if(!cur) return NULL; + + OOTRACEDBGC4("Found matching t38 capability type %s. Comparing" + " other parameters. (%s, %s)\n", ooGetCapTypeText(cap), + call->callType, call->callToken); + + /* can we receive this capability */ + if(dir & OORX) + { + OOTRACEDBGC4("We can receive Simple capability %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + epCap = (ooH323EpCapability*)memAllocZ(call->pctxt, + sizeof(ooH323EpCapability)); + params=(OOCapParams*)memAlloc(call->pctxt,sizeof(OOCapParams)); + if(!epCap || !params) + { + OOTRACEERR3("Error:Memory - ooIsT38Supported - " + "epCap/params (%s, %s)\n", call->callType, + call->callToken); + return NULL; + } + epCap->params = params; + epCap->cap = cur->cap; + epCap->dir = cur->dir; + epCap->capType = cur->capType; + epCap->startReceiveChannel = cur->startReceiveChannel; + epCap->startTransmitChannel= cur->startTransmitChannel; + epCap->stopReceiveChannel = cur->stopReceiveChannel; + epCap->stopTransmitChannel = cur->stopTransmitChannel; + epCap->next = NULL; + memcpy(epCap->params, cur->params, sizeof(OOCapParams)); + OOTRACEDBGC4("Returning copy of matched receive capability %s. " + "(%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + return epCap; + } + + /* Can we transmit compatible stream */ + if(dir & OOTX) + { + OOTRACEDBGC4("We can transmit Simple capability %s. (%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + epCap = (ooH323EpCapability*)memAlloc(call->pctxt, + sizeof(ooH323EpCapability)); + params =(OOCapParams*)memAllocZ(call->pctxt,sizeof(OOCapParams)); + if(!epCap || !params) + { + OOTRACEERR3("Error:Memory - ooIsAudioDataTypeSimpleSupported - " + "epCap/params (%s, %s)\n", call->callType, + call->callToken); + return NULL; + } + epCap->params = params; + epCap->cap = cur->cap; + epCap->dir = cur->dir; + epCap->capType = cur->capType; + epCap->startReceiveChannel = cur->startReceiveChannel; + epCap->startTransmitChannel= cur->startTransmitChannel; + epCap->stopReceiveChannel = cur->stopReceiveChannel; + epCap->stopTransmitChannel = cur->stopTransmitChannel; + epCap->next = NULL; + memcpy(epCap->params, cur->params, sizeof(OOCapParams)); + OOTRACEDBGC4("Returning copy of matched transmit capability %s." + "(%s, %s)\n", + ooGetCapTypeText(cur->cap), call->callType, + call->callToken); + return epCap; + } + return NULL; +} ooH323EpCapability* ooIsVideoDataTypeH263Supported (OOH323CallData *call, H245H263VideoCapability* pH263Cap, int dir, @@ -1828,10 +2434,12 @@ OOTRACEDBGC3("Looking for audio dataType support. (%s, %s)\n", call->callType, call->callToken); return ooIsAudioDataTypeSupported(call, data->u.audioData, dir); + case T_H245DataType_data: - OOTRACEDBGC3("Data type not supported.(%s, %s)\n", + OOTRACEDBGC3("Looking for application data dataType support.(%s, %s)\n", call->callType, call->callToken); - return NULL; + return ooIsT38Supported(call, data->u.data, dir); + case T_H245DataType_encryptionData: OOTRACEDBGC3("Encryption data type not supported.(%s, %s)\n", call->callType, call->callToken); @@ -1958,7 +2566,6 @@ return OO_OK; } - int ooAddRemoteCapability(OOH323CallData *call, H245Capability *cap) { switch(cap->t) @@ -1972,6 +2579,19 @@ case T_H245Capability_receiveAndTransmitAudioCapability: return ooAddRemoteAudioCapability(call, cap->u.receiveAndTransmitAudioCapability, OORXTX); + + + case T_H245Capability_receiveDataApplicationCapability: + return ooAddRemoteDataApplicationCapability(call, cap->u.receiveDataApplicationCapability, + OORX); + case T_H245Capability_transmitDataApplicationCapability: + return ooAddRemoteDataApplicationCapability(call, cap->u.transmitDataApplicationCapability, + OOTX); + case T_H245Capability_receiveAndTransmitDataApplicationCapability: + return ooAddRemoteDataApplicationCapability(call, + cap->u.receiveAndTransmitDataApplicationCapability, OORXTX); + + default: OOTRACEDBGA3("Unsupported cap type encountered. Ignoring. (%s, %s)\n", call->callType, call->callToken); @@ -1979,6 +2599,23 @@ return OO_OK; } +int ooAddRemoteDataApplicationCapability(OOH323CallData *call, + H245DataApplicationCapability *dataCap, + int dir) +{ + switch(dataCap->application.t) + { + case T_H245DataApplicationCapability_application_t38fax: + return ooCapabilityAddT38Capability(call, OO_T38, + dir, NULL, NULL, NULL, NULL,TRUE); + default: + OOTRACEDBGA1("Unsupported data capability type\n"); + + } + return OO_OK; +} + + int ooAddRemoteAudioCapability(OOH323CallData *call, H245AudioCapability *audioCap, int dir) @@ -2034,6 +2671,35 @@ return ooCapabilityAddSimpleCapability(call, OO_G726, txframes, rxframes, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); */ + case T_H245AudioCapability_nonStandard: + if (audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard && + audioCap->u.nonStandard->data.numocts == sizeof("G.726-32k")-1 && + !strncmp(audioCap->u.nonStandard->data.data, "G.726-32k", + audioCap->u.nonStandard->data.numocts)) + return ooCapabilityAddSimpleCapability(call, OO_G726, 20, + 240, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); + + if (audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard && + audioCap->u.nonStandard->data.numocts == sizeof("G726r32")-1 && + !strncmp(audioCap->u.nonStandard->data.data, "G726r32", + audioCap->u.nonStandard->data.numocts)) + return ooCapabilityAddSimpleCapability(call, OO_G726AAL2, 20, + 240, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); + + if (audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard && + audioCap->u.nonStandard->data.numocts == sizeof("AMRNB")-1 && + !strncmp(audioCap->u.nonStandard->data.data, "AMRNB", + audioCap->u.nonStandard->data.numocts)) + return ooCapabilityAddSimpleCapability(call, OO_AMRNB, 4, + 4, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); + break; + case T_H245AudioCapability_g728: if(dir&OOTX) txframes = audioCap->u.g728; else if(dir&OORX) rxframes = audioCap->u.g728; @@ -2064,6 +2730,16 @@ return ooCapabilityAddSimpleCapability(call, OO_G729A, txframes, rxframes, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); + case T_H245AudioCapability_g729wAnnexB: + if(dir&OOTX) txframes = audioCap->u.g729wAnnexB; + else if(dir&OORX) rxframes = audioCap->u.g729wAnnexB; + else{ + txframes = audioCap->u.g729wAnnexB; + rxframes = audioCap->u.g729wAnnexB; + } + return ooCapabilityAddSimpleCapability(call, OO_G729B, txframes, + rxframes, FALSE, dir, NULL, NULL, NULL, NULL, TRUE); + case T_H245AudioCapability_g7231: if(dir&OOTX) txframes = audioCap->u.g7231->maxAl_sduAudioFrames; else if(dir&OORX) rxframes = audioCap->u.g7231->maxAl_sduAudioFrames; @@ -2101,10 +2777,6 @@ return OO_OK; } - - - - int ooCapabilityUpdateJointCapabilities (OOH323CallData* call, H245Capability *cap) { @@ -2123,7 +2795,9 @@ OORX); break; case T_H245Capability_receiveAndTransmitAudioCapability: - epCap = NULL; + epCap = ooIsAudioDataTypeSupported(call, cap->u.receiveAudioCapability, OOTX); + if (!epCap) + epCap = ooIsAudioDataTypeSupported(call, cap->u.transmitAudioCapability, OORX); break; case T_H245Capability_receiveVideoCapability: return ooCapabilityUpdateJointCapabilitiesVideo(call, @@ -2131,6 +2805,22 @@ case T_H245Capability_transmitVideoCapability: return ooCapabilityUpdateJointCapabilitiesVideo(call, cap->u.transmitVideoCapability, OORX); + + case T_H245Capability_receiveDataApplicationCapability: + epCap= ooIsT38Supported(call, cap->u.receiveDataApplicationCapability, + OOTX); + break; + case T_H245Capability_transmitDataApplicationCapability: + epCap = ooIsT38Supported(call, cap->u.transmitDataApplicationCapability, + OORX); + break; + case T_H245Capability_receiveAndTransmitDataApplicationCapability: + epCap = ooIsT38Supported(call, cap->u.receiveAndTransmitDataApplicationCapability, OOTX); + if (!epCap) + epCap = ooIsT38Supported(call, cap->u.receiveAndTransmitDataApplicationCapability, OORX); + break; + + case T_H245Capability_receiveUserInputCapability: if((cap->u.receiveUserInputCapability->t == T_H245UserInputCapability_basicString) && @@ -2310,7 +3000,7 @@ { static const char *capTypes[]={ "unknown", - "OO_NONSTANDARD", + "OO_G726", "OO_G711ALAW64K", "OO_G711ALAW56K", "OO_G711ULAW64K", @@ -2322,8 +3012,8 @@ "OO_G728", "OO_G729", "OO_G729ANNEXA", - "OO_IS11172AUDIO", - "OO_IS13818AUDIO", + "OO_AMRNB", + "OO_G726AAL2", "OO_G729WANNEXB", "OO_G729ANNEXAWANNEXB", "OO_G7231ANNEXC", @@ -2343,7 +3033,8 @@ "OO_H263VIDEO", "OO_IS11172VIDEO", /* mpeg */ "OO_GENERICVIDEO", - "OO_EXTELEMVIDEO" + "OO_EXTELEMVIDEO", + "OO_T38" /* T.38 */ }; return ooUtilsGetText (cap, capTypes, OONUMBEROF(capTypes)); }