--- ../bb/asterisk-addons-1.6.1.0/channels/ooh323cDriver.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323cDriver.h 2009-10-13 05:17:17.000000000 +0400 @@ -27,13 +27,16 @@ #define H323_DTMF_H245ALPHANUMERIC (1 << 2) #define H323_DTMF_H245SIGNAL (1 << 3) #define H323_DTMF_INBAND (1 << 4) +#define H323_DTMF_CISCO (1 << 5) +#define H323_DTMF_INBANDRELAX (1 << 8) struct h323_pvt; int ooh323c_start_stack_thread(void); int ooh323c_stop_stack_thread(void); int ooh323c_set_capability - (struct ast_codec_pref *prefs, int capability, int dtmf); + (struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec); int 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 dtmfcode, + int t38support); #endif --- ../bb/asterisk-addons-1.6.1.0/channels/chan_ooh323.h 2008-05-28 18:45:23.000000000 +0400 +++ channels/chan_ooh323.h 2009-08-04 04:59:40.000000000 +0400 @@ -61,6 +61,8 @@ #include #include +#include + #include "ootypes.h" #include "ooCapability.h" #include "oochannels.h" @@ -95,7 +97,7 @@ struct ast_frame *ooh323_rtp_read (struct ast_channel *ast, struct ooh323_pvt *p); -void ooh323_set_write_format(ooCallData *call, int fmt); +void ooh323_set_write_format(ooCallData *call, int fmt, int txframes); void ooh323_set_read_format(ooCallData *call, int fmt); int ooh323_update_capPrefsOrderForCall --- ../bb/asterisk-addons-1.6.1.0/channels/chan_ooh323.c 2008-06-04 21:35:29.000000000 +0400 +++ channels/chan_ooh323.c 2009-10-18 01:35:52.000000000 +0400 @@ -16,6 +16,15 @@ #include "chan_ooh323.h" +#include +#include + +#define HAVE_SPANDSP_EXPOSE_H +#include +#ifdef HAVE_SPANDSP_EXPOSE_H +#include +#endif +#include /* Defaults */ #define DEFAULT_CONTEXT "default" @@ -32,12 +41,27 @@ #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"; static const char tdesc[] = "Objective Systems H323 Channel Driver"; static const char config[] = "ooh323.conf"; +static struct ast_jb_conf default_jbconf = +{ + .flags = 0, + .max_size = -1, + .resync_threshold = -1, + .impl = "" +}; +static struct ast_jb_conf global_jbconf; /* Channel Definition */ static struct ast_channel *ooh323_request(const char *type, int format, @@ -50,6 +74,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 +82,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 +105,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 +116,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; @@ -119,12 +171,16 @@ int capability; struct ast_codec_pref prefs; int dtmfmode; + int dtmfcodec; char exten[AST_MAX_EXTENSION]; /* Requested extension */ char context[AST_MAX_EXTENSION]; /* Context where to start */ char accountcode[256]; /* Account code */ int nat; int amaflags; + int progsent; /* progress is sent */ struct ast_dsp *vad; + struct OOH323Regex *rtpmask; /* rtp ip regexp */ + char rtpmaskstr[120]; struct ooh323_pvt *next; /* Next entity */ } *iflist = NULL; @@ -143,9 +199,13 @@ int capability; struct ast_codec_pref prefs; int dtmfmode; + int dtmfcodec; + int t38support; int rtptimeout; int mUseIP; /* Use IP address or H323-ID to search user */ char mIP[20]; + struct OOH323Regex *rtpmask; + char rtpmaskstr[120]; struct ooh323_user *next; }; @@ -160,6 +220,8 @@ char accountcode[20]; int amaflags; int dtmfmode; + int dtmfcodec; + int t38support; int mFriend; /* indicates defined as friend */ char ip[20]; int port; @@ -168,6 +230,8 @@ char *url; /* url alias, which asterisk will register with gk to reach this peer*/ char *e164; /* e164 alias, which asterisk will register with gk to reach this peer*/ int rtptimeout; + struct OOH323Regex *rtpmask; + char rtpmaskstr[120]; struct ooh323_peer *next; }; @@ -193,35 +257,51 @@ 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 gDTMFCodec = 101; +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,38 +324,48 @@ 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; + int fmt = 0; if (gH323Debug) - ast_verbose("--- ooh323_new - %s\n", host); + ast_verbose("--- ooh323_new - %s, %d\n", host, capability); /* 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); + if (capability) + fmt = ast_best_codec(capability); + if (!fmt) + fmt = ast_codec_pref_index(&i->prefs, 0); + + 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)); - ch->fds[0] = ast_rtp_fd(i->rtp); - ch->fds[1] = ast_rtcp_fd(i->rtp); + ast_jb_configure(ch, &global_jbconf); 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; + ast_set_write_format(ch, fmt); + ast_set_read_format(ch, fmt); ch->tech_pvt = i; i->owner = ch; @@ -283,6 +373,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 +393,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 +421,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 +460,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 +469,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 +481,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); @@ -396,8 +503,10 @@ OO_SETFLAG(pvt->flags, H323_DISABLEGK); pvt->dtmfmode = gDTMFMode; + pvt->dtmfcodec = gDTMFCodec; 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 +529,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 +565,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 +604,26 @@ 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->dtmfcodec = peer->dtmfcodec; + p->t38support = peer->t38support; + if (peer->rtpmask && peer->rtpmaskstr[0]) { + p->rtpmask = peer->rtpmask; + ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr)); + } ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode)); p->amaflags = peer->amaflags; } else { p->dtmfmode = gDTMFMode; + p->dtmfcodec = gDTMFCodec; + p->t38support = gT38Support; p->capability = gCapability; memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref)); @@ -523,7 +639,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 +647,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 +701,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 +713,7 @@ break; } } + ast_mutex_unlock(&userl.lock); if (gH323Debug) @@ -627,6 +761,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 +805,22 @@ 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); ooSendDTMFDigit(p->callToken, dtmf); - ast_mutex_unlock(&ooh323c_cmd_lock); } ast_mutex_unlock(&p->lock); if (gH323Debug) @@ -700,7 +841,7 @@ return -1; } ast_mutex_lock(&p->lock); - if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) + if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO)) ) ast_rtp_senddigit_end(p->rtp, digit); ast_mutex_unlock(&p->lock); @@ -715,18 +856,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 +878,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 +902,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 +914,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 +921,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 +952,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 +960,37 @@ 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)); - ast_mutex_unlock(&ooh323c_cmd_lock); + ooHangCall(p->callToken, + ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause); 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 +1007,7 @@ } else { ast_log(LOG_ERROR, "No call to hangup\n" ); - return -1; + /* return -1; */ } if (gH323Debug) @@ -863,17 +1023,19 @@ 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); + ooAnswerCall(p->callToken); + } + ast_mutex_unlock(&p->lock); } - ast_mutex_unlock(&p->lock); if (gH323Debug) ast_verbose("+++ ooh323_answer\n"); @@ -887,6 +1049,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 +1065,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_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 (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 (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 +1170,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,21 +1185,18 @@ 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); - ast_mutex_unlock(&ooh323c_cmd_lock); + ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, + AST_CAUSE_SWITCH_CONGESTION); ast_set_flag(p, H323_ALREADYGONE); } break; case AST_CONTROL_BUSY: if (!ast_test_flag(p, H323_ALREADYGONE)) { - ast_mutex_lock(&ooh323c_cmd_lock); - ooHangCall(callToken, OO_REASON_LOCAL_BUSY); - ast_mutex_unlock(&ooh323c_cmd_lock); + ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY); ast_set_flag(p, H323_ALREADYGONE); } break; @@ -970,9 +1206,71 @@ case AST_CONTROL_UNHOLD: ast_moh_stop(ast); break; - case AST_CONTROL_PROCEEDING: - case AST_CONTROL_RINGING: case AST_CONTROL_PROGRESS: + if (ast->_state != AST_STATE_UP) { + if (!p->progsent) { + if (gH323Debug) + ast_log(LOG_DEBUG,"Sending manual progress for %s, res = %d\n", callToken, + ooManualProgress(callToken)); + else + ooManualProgress(callToken); + p->progsent = 1; + } + } + break; + case AST_CONTROL_RINGING: + if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING) { + if (gH323Debug) + ast_log(LOG_DEBUG,"Sending manual ringback for %s, res = %d\n", + callToken, + ooManualRingback(callToken)); + else + ooManualRingback(callToken); + } + 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 +1278,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; @@ -1016,15 +1366,14 @@ } -void ooh323_set_write_format(ooCallData *call, int fmt) +void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) { -#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/%d\n", + ast_getformatname_multiple(formats,512, fmt), txframes); p = find_call(call); if (!p) { @@ -1035,34 +1384,50 @@ 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)); + if (txframes) + ast_codec_pref_setsize(&p->prefs, fmt, txframes); + ast_rtp_codec_setpref(p->rtp, &p->prefs); + 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 +1435,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,38 +1476,88 @@ 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 (!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; +} + /** * Callback for sending digits from H.323 up to asterisk * @@ -1150,8 +1588,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 +1610,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 +1642,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 +1680,65 @@ /* 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->dtmfcodec = user->dtmfcodec; + p->t38support = user->t38support; + if (user->rtpmask && user->rtpmaskstr[0]) { + p->rtpmask = user->rtpmask; + ast_copy_string(p->rtpmaskstr, user->rtpmaskstr, + sizeof(p->rtpmaskstr)); + } /* 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); + 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_set_flag(p, H323_ALREADYGONE); + 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->dtmfcodec, 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 +1750,112 @@ +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); + } + } + if (p->rtpmask && p->rtpmaskstr[0]) { + call->rtpMask = p->rtpmask; + ast_mutex_lock(&call->rtpMask->lock); + call->rtpMask->inuse++; + ast_mutex_unlock(&call->rtpMask->lock); + ast_copy_string(call->rtpMaskStr, p->rtpmaskstr, sizeof(call->rtpMaskStr)); + } + + 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"); + ast_mutex_unlock(&call->Lock); 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 +1892,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->dtmfcodec, 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 +1915,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 +1960,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 +2009,6 @@ return OO_OK; } -#if 0 static void ooh323_delete_user(struct ooh323_user *user) { struct ooh323_user *prev = NULL, *cur = NULL; @@ -1469,7 +2040,6 @@ ast_verbose("+++ ooh323_delete_user\n"); } -#endif void ooh323_delete_peer(struct ooh323_peer *peer) { @@ -1479,36 +2049,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,14 +2087,17 @@ if (gH323Debug) ast_verbose("--- build_user\n"); - user = ast_calloc(1, sizeof(*user)); + user = ast_calloc(1,sizeof(struct ooh323_user)); if (user) { + memset(user, 0, sizeof(struct ooh323_user)); ast_mutex_init(&user->lock); ast_copy_string(user->name, name, sizeof(user->name)); user->capability = gCapability; memcpy(&user->prefs, &gPrefs, sizeof(user->prefs)); user->rtptimeout = gRTPTimeout; user->dtmfmode = gDTMFMode; + user->dtmfcodec = gDTMFCodec; + 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,35 +2111,67 @@ 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, "rtpmask")) { + if ((user->rtpmask = malloc(sizeof(struct OOH323Regex))) && + (regcomp(&user->rtpmask->regex, v->value, REG_EXTENDED) + == 0)) { + ast_mutex_init(&user->rtpmask->lock); + user->rtpmask->inuse = 1; + ast_copy_string(user->rtpmaskstr, v->value, + sizeof(user->rtpmaskstr)); + } else user->rtpmask = NULL; } 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; + if (!strcasecmp(v->value, "cisco")) + user->dtmfmode = H323_DTMF_CISCO; else if (!strcasecmp(v->value, "q931keypad")) user->dtmfmode = H323_DTMF_Q931; else if (!strcasecmp(v->value, "h245alphanumeric")) 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, "dtmfcodec") && atoi(v->value)) { + user->dtmfcodec = atoi(v->value); + } 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 +2196,21 @@ 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->dtmfcodec = gDTMFCodec; + 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 +2241,27 @@ 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, "rtpmask")) { + if ((peer->rtpmask = malloc(sizeof(struct OOH323Regex))) && + (regcomp(&peer->rtpmask->regex, v->value, REG_EXTENDED) + == 0)) { + ast_mutex_init(&peer->rtpmask->lock); + peer->rtpmask->inuse = 1; + ast_copy_string(peer->rtpmaskstr, v->value, + sizeof(peer->rtpmaskstr)); + } else peer->rtpmask = NULL; } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); @@ -1661,12 +2277,31 @@ } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "rfc2833")) peer->dtmfmode = H323_DTMF_RFC2833; + if (!strcasecmp(v->value, "cisco")) + peer->dtmfmode = H323_DTMF_CISCO; else if (!strcasecmp(v->value, "q931keypad")) peer->dtmfmode = H323_DTMF_Q931; else if (!strcasecmp(v->value, "h245alphanumeric")) 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, "dtmfcodec") && atoi(v->value)) { + peer->dtmfcodec = atoi(v->value); + } 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 +2319,7 @@ ast_verbose("--- ooh323_do_reload\n"); } - reload_config(1); + reload_config(1); if (gH323Debug) { ast_verbose("+++ ooh323_do_reload\n"); @@ -1693,19 +2328,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 +2364,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 +2397,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 +2415,12 @@ 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; + gDTMFCodec = 101; + gT38Support = T38_FAXGW; + gTRCLVL = OOTRCLVLERR; gRasGkMode = RasNoGatekeeper; gGatekeeper[0] = '\0'; gRTPTimeout = 60; @@ -1777,6 +2436,11 @@ v = ast_variable_browse(cfg, "general"); while (v) { + + if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { + v = v->next; + continue; + } if (!strcasecmp(v->name, "port")) { gPort = (int)strtol(v->value, NULL, 10); @@ -1784,7 +2448,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 +2457,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 +2480,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 +2512,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 +2522,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,19 +2545,20 @@ 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) gRTPTimeout = 60; } else if (!strcasecmp(v->name, "tos")) { - if (sscanf(v->value, "%i", &format) == 1) + if (sscanf(v->value, "%30i", &format) == 1) gTOS = format & 0xff; else if (!strcasecmp(v->value, "lowdelay")) gTOS = IPTOS_LOWDELAY; @@ -1897,7 +2577,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")) { @@ -1911,6 +2591,8 @@ gDTMFMode = H323_DTMF_INBAND; else if (!strcasecmp(v->value, "rfc2833")) gDTMFMode = H323_DTMF_RFC2833; + else if (!strcasecmp(v->value, "cisco")) + gDTMFMode = H323_DTMF_CISCO; else if (!strcasecmp(v->value, "q931keypad")) gDTMFMode = H323_DTMF_Q931; else if (!strcasecmp(v->value, "h245alphanumeric")) @@ -1918,10 +2600,29 @@ 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, "dtmfcodec") && atoi(v->value)) { + gDTMFCodec = atoi(v->value); + } 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 +2674,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 +2697,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 +2712,51 @@ } 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: "); - if (peer->dtmfmode & H323_DTMF_RFC2833) - ast_cli(a->fd, "%s\n", "rfc2833"); - else if (peer->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); + 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_CISCO) { + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + } else if (peer->dtmfmode & H323_DTMF_RFC2833) { + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + } else if (peer->dtmfmode & H323_DTMF_Q931) + 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_mutex_unlock(&peer->lock); + 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); + if (peer->rtpmaskstr[0]) + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr); + 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 +2765,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 +2784,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 +2841,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 +2856,51 @@ } 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: "); - if (user->dtmfmode & H323_DTMF_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, "%-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_CISCO) { + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + } else if (user->dtmfmode & H323_DTMF_RFC2833) { + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + } else if (user->dtmfmode & H323_DTMF_Q931) + 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); + if (user->rtpmaskstr[0]) + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); 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 +2909,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 +2927,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 +2999,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 +3029,63 @@ 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: "); - if (gDTMFMode & H323_DTMF_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, "%-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_CISCO) { + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); + } else if (gDTMFMode & H323_DTMF_RFC2833) { + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); + } else if (gDTMFMode & H323_DTMF_Q931) + 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 +3096,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 +3110,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 +3154,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 +3192,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 +3223,11 @@ if (!gTunneling) ooH323EpDisableH245Tunneling(); + if (gBeMaster) + ooH323EpTryBeMaster(1); + + ooH323EpEnableManualRingback(); + /* Gatekeeper */ if (gRasGkMode == RasUseSpecificGatekeeper) ooGkClientInit(gRasGkMode, gGatekeeper, 0); @@ -2451,22 +3238,23 @@ ooH323EpSetH323Callbacks(h323Callbacks); /* Add endpoint capabilities */ - if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode) < 0) { + if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode, gDTMFCodec) < 0) { ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n"); 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 +3284,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 +3295,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 +3366,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 +3390,7 @@ iflist = cur->next; if (cur->callToken) { + if (gH323Debug) ast_verbose(" Destroying %s\n", cur->callToken); free(cur->callToken); cur->callToken = 0; } @@ -2615,15 +3415,24 @@ cur->callerid_num = 0; } - if (cur->rtp) { 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 +3443,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 +3482,20 @@ 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); + if(prev->rtpmask) { + ast_mutex_lock(&prev->rtpmask->lock); + prev->rtpmask->inuse--; + ast_mutex_unlock(&prev->rtpmask->lock); + if (prev->rtpmask->inuse == 0) { + regfree(&prev->rtpmask->regex); + ast_mutex_destroy(&prev->rtpmask->lock); + free(prev->rtpmask); + } + } free(prev); if (cur == peerl.peers) { @@ -2684,6 +3516,17 @@ prev = cur; cur = cur->next; ast_mutex_destroy(&prev->lock); + + if(prev->rtpmask) { + ast_mutex_lock(&prev->rtpmask->lock); + prev->rtpmask->inuse--; + ast_mutex_unlock(&prev->rtpmask->lock); + if (prev->rtpmask->inuse == 0) { + regfree(&prev->rtpmask->regex); + ast_mutex_destroy(&prev->rtpmask->lock); + free(prev->rtpmask); + } + } free(prev); if (cur == userl.users) { break; @@ -2705,8 +3548,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 +3723,29 @@ return OO_G711ALAW64K; case AST_FORMAT_GSM: return OO_GSMFULLRATE; + +#ifdef AST_FORMAT_AMRNB + case AST_FORMAT_AMRNB: + return OO_AMRNB; +#endif +#ifdef AST_FORMAT_SPEEX + case AST_FORMAT_SPEEX: + return OO_SPEEX; +#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; } } @@ -2934,7 +3791,15 @@ if (p->rtp) { ast_rtp_codec_setpref(p->rtp, &p->prefs); - } + if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) { + ast_rtp_set_rtpmap_type(p->rtp, p->dtmfcodec, "audio", + "telephone-event", 0); + } + if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) { + ast_rtp_set_rtpmap_type(p->rtp, p->dtmfcodec, "audio", + "cisco-telephone-event", 0); + } + } /* figure out our local RTP port and tell the H.323 stack about it*/ ast_rtp_get_us(p->rtp, &us); @@ -2954,9 +3819,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"); @@ -2970,7 +3851,7 @@ struct sockaddr_in them; if (gH323Debug) - ast_verbose("--- setup_rtp_connection\n"); + ast_verbose("--- setup_rtp_connection %s:%d\n", remoteIp, remotePort); /* Find the call or allocate a private structure if call not found */ p = find_call(call); @@ -2985,9 +3866,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 +3879,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 +3894,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 +4058,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 +4092,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 +4362,8 @@ } return 0; + + } int ooh323_convert_hangupcause_h323ToAsterisk(int cause) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323cDriver.c 2008-05-28 18:45:23.000000000 +0400 +++ channels/ooh323cDriver.c 2009-10-20 01:08:30.000000000 +0400 @@ -16,22 +16,47 @@ #include "ooh323cDriver.h" +#include +#include + #include #include -#include + +#undef AST_BACKGROUND_STACKSIZE +#define AST_BACKGROUND_STACKSIZE 768 * 1024 + +#define SEC_TO_HOLD_THREAD 24 extern OOBOOL gH323Debug; +extern OOH323EndPoint gH323ep; /* ooh323c stack thread. */ static pthread_t ooh323c_thread = AST_PTHREADT_NULL; +static pthread_t ooh323cmd_thread = AST_PTHREADT_NULL; static int grxframes = 240; static int gtxframes = 20; +static struct callthread { + ast_mutex_t lock; + int thePipe[2]; + OOBOOL inUse; + ooCallData* call; + struct callthread *next, *prev; +} *callThreads = NULL; + +AST_MUTEX_DEFINE_STATIC(callThreadsLock); + + int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel); int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel); int ooh323c_stop_receive_channel(ooCallData *call, ooLogicalChannel *pChannel); int ooh323c_stop_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel); +int ooh323c_start_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel); +int ooh323c_start_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel); +int ooh323c_stop_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel); +int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel); + void* ooh323c_stack_thread(void* dummy) { @@ -39,13 +64,143 @@ return dummy; } +void* ooh323c_cmd_thread(void* dummy) +{ + + ooMonitorCmdChannels(); + return dummy; +} + +void* ooh323c_call_thread(void* dummy) +{ + struct callthread* mycthread = (struct callthread *)dummy; + struct timespec ts; + struct pollfd pfds[1]; + char c; + + do { + + ooMonitorCallChannels((ooCallData*)mycthread->call); + mycthread->call = NULL; + mycthread->prev = NULL; + mycthread->inUse = FALSE; + + ast_mutex_lock(&callThreadsLock); + mycthread->next = callThreads; + callThreads = mycthread; + if (mycthread->next) mycthread->next->prev = mycthread; + ast_mutex_unlock(&callThreadsLock); + + pfds[0].fd = mycthread->thePipe[0]; + pfds[0].events = POLLIN; + ooSocketPoll(pfds, 1, SEC_TO_HOLD_THREAD * 1000); + if (ooPDRead(pfds, 1, mycthread->thePipe[0])) + read(mycthread->thePipe[0], &c, 1); + + ast_mutex_lock(&callThreadsLock); + ast_mutex_lock(&mycthread->lock); + if (mycthread->prev) + mycthread->prev->next = mycthread->next; + else + callThreads = mycthread->next; + if (mycthread->next) + mycthread->next->prev = mycthread->prev; + ast_mutex_unlock(&mycthread->lock); + ast_mutex_unlock(&callThreadsLock); + + } while (mycthread->call != NULL); + + + ast_mutex_destroy(&mycthread->lock); + + free(mycthread); + return dummy; +} + +int ooh323c_start_call_thread(ooCallData *call) { + pthread_attr_t attr; + char c = 'c'; + struct callthread *cur = callThreads; + + ast_mutex_lock(&callThreadsLock); + while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) { + cur = cur->next; + } + ast_mutex_unlock(&callThreadsLock); + + if (cur != NULL && cur->inUse) { + ast_mutex_unlock(&cur->lock); + cur = NULL; + } + +/* make new thread */ + if (cur == NULL) { + if (!(cur = ast_malloc(sizeof(struct callthread)))) { + ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n", + call->callToken); + return -1; + } + + memset(cur, 0, sizeof(cur)); + if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) { + ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken); + free(cur); + return -1; + } + cur->inUse = TRUE; + cur->call = call; + + ast_mutex_init(&cur->lock); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if (gH323Debug) + ast_debug(1,"new call thread created for call %s\n", call->callToken); + + if(ast_pthread_create_background(&call->callThread, &attr, ooh323c_call_thread, cur) < 0) + { + ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", + call->callToken); + pthread_attr_destroy(&attr); + ast_mutex_destroy(&cur->lock); + free(cur); + return -1; + } + pthread_attr_destroy(&attr); + + } else { + if (gH323Debug) + ast_debug(1,"using existing call thread for call %s\n", call->callToken); + cur->inUse = TRUE; + cur->call = call; + write(cur->thePipe[1], &c, 1); + ast_mutex_unlock(&cur->lock); + + } + return 0; +} + + +int ooh323c_stop_call_thread(ooCallData *call) { + if (call->callThread != AST_PTHREADT_NULL) { + ooStopMonitorCallChannels(call); + } + return 0; +} + int ooh323c_start_stack_thread() { - if(ast_pthread_create(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0) + if(ast_pthread_create_background(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0) { ast_log(LOG_ERROR, "Unable to start ooh323c thread.\n"); return -1; } + if(ast_pthread_create_background(&ooh323cmd_thread, NULL, ooh323c_cmd_thread, NULL) < 0) + { + ast_log(LOG_ERROR, "Unable to start ooh323cmd thread.\n"); + return -1; + } return 0; } @@ -56,12 +211,14 @@ ooStopMonitor(); pthread_join(ooh323c_thread, NULL); ooh323c_thread = AST_PTHREADT_NULL; + pthread_join(ooh323cmd_thread, NULL); + ooh323cmd_thread = AST_PTHREADT_NULL; } return 0; } int ooh323c_set_capability - (struct ast_codec_pref *prefs, int capability, int dtmf) + (struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec) { int ret, x, format=0; if(gH323Debug) @@ -107,13 +264,44 @@ &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); + if(gH323Debug) + ast_verbose("\tAdding g729b capability to H323 endpoint\n"); + ret |= ooH323EpAddG729Capability(OO_G729B, 2, 24, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); } if(format & AST_FORMAT_G723_1) { if(gH323Debug) ast_verbose("\tAdding g7231 capability to H323 endpoint\n"); - ret = ooH323EpAddG7231Capability(OO_G7231, 4, 7, FALSE, + ret = ooH323EpAddG7231Capability(OO_G7231, 1, 1, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } + + if(format & AST_FORMAT_G726) + { + if(gH323Debug) + ast_verbose("\tAdding g726 capability to H323 endpoint\n"); + ret = ooH323EpAddG726Capability(OO_G726, gtxframes, grxframes, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } + + if(format & AST_FORMAT_G726_AAL2) + { + if(gH323Debug) + ast_verbose("\tAdding g726aal2 capability to H323 endpoint\n"); + ret = ooH323EpAddG726Capability(OO_G726AAL2, gtxframes, grxframes, FALSE, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, @@ -145,8 +333,38 @@ } +#ifdef AST_FORMAT_AMRNB + if(format & AST_FORMAT_AMRNB) + { + if(gH323Debug) + ast_verbose("\tAdding amr nb capability to H323 endpoint\n"); + ret = ooH323EpAddAMRNBCapability(OO_AMRNB, 4, 4, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } +#endif + +#ifdef AST_FORMAT_SPEEX + if(format & AST_FORMAT_SPEEX) + { + if(gH323Debug) + ast_verbose("\tAdding speex capability to H323 endpoint\n"); + ret = ooH323EpAddSpeexCapability(OO_SPEEX, 4, 4, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } +#endif + } + if(dtmf & H323_DTMF_CISCO) + ret |= ooH323EpEnableDTMFCISCO(0); if(dtmf & H323_DTMF_RFC2833) ret |= ooH323EpEnableDTMFRFC2833(0); else if(dtmf & H323_DTMF_H245ALPHANUMERIC) @@ -158,20 +376,30 @@ } int ooh323c_set_capability_for_call - (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf) + (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec, + int t38support) { int ret, x, txframes; int format=0; if(gH323Debug) ast_verbose("\tAdding capabilities to call(%s, %s)\n", call->callType, call->callToken); - if(dtmf & H323_DTMF_RFC2833) - ret |= ooCallEnableDTMFRFC2833(call,0); - else if(dtmf & H323_DTMF_H245ALPHANUMERIC) + if(dtmf & H323_DTMF_CISCO || 1) + ret |= ooCallEnableDTMFCISCO(call,dtmfcodec); + if(dtmf & H323_DTMF_RFC2833 || 1) + ret |= ooCallEnableDTMFRFC2833(call,dtmfcodec); + if(dtmf & H323_DTMF_H245ALPHANUMERIC || 1) ret |= ooCallEnableDTMFH245Alphanumeric(call); - else if(dtmf & H323_DTMF_H245SIGNAL) + if(dtmf & H323_DTMF_H245SIGNAL || 1) ret |= ooCallEnableDTMFH245Signal(call); + if (t38support) + ooCapabilityAddT38Capability(call, OO_T38, OORXANDTX, + &ooh323c_start_receive_datachannel, + &ooh323c_start_transmit_datachannel, + &ooh323c_stop_receive_datachannel, + &ooh323c_stop_transmit_datachannel, + 0); for(x=0; 0 !=(format=ast_codec_pref_index(prefs, x)); x++) { @@ -182,7 +410,7 @@ call->callType, call->callToken); txframes = prefs->framing[x]; ret= ooCallAddG711Capability(call, OO_G711ULAW64K, txframes, - grxframes, OORXANDTX, + txframes, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, @@ -195,33 +423,70 @@ call->callType, call->callToken); txframes = prefs->framing[x]; ret= ooCallAddG711Capability(call, OO_G711ALAW64K, txframes, - grxframes, OORXANDTX, + txframes, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); } + if(format & AST_FORMAT_G726) + { + if(gH323Debug) + ast_verbose("\tAdding g726 capability to call (%s, %s)\n", + call->callType, call->callToken); + txframes = prefs->framing[x]; + ret = ooCallAddG726Capability(call, OO_G726, txframes, grxframes, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } + + if(format & AST_FORMAT_G726_AAL2) + { + if(gH323Debug) + ast_verbose("\tAdding g726aal2 capability to call (%s, %s)\n", + call->callType, call->callToken); + txframes = prefs->framing[x]; + ret = ooCallAddG726Capability(call, OO_G726AAL2, txframes, grxframes, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + + } + if(format & AST_FORMAT_G729A) { + + txframes = (prefs->framing[x])/10; + if(gH323Debug) + ast_verbose("\tAdding g729 capability to call(%s, %s)\n", + call->callType, call->callToken); + ret|= ooCallAddG729Capability(call, OO_G729, txframes, txframes, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); if(gH323Debug) ast_verbose("\tAdding g729A capability to call(%s, %s)\n", call->callType, call->callToken); - txframes = (prefs->framing[x])/10; - ret= ooCallAddG729Capability(call, OO_G729A, txframes, 24, + ret= ooCallAddG729Capability(call, OO_G729A, txframes, txframes, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); - if(gH323Debug) - ast_verbose("\tAdding g729 capability to call(%s, %s)\n", + ast_verbose("\tAdding g729B capability to call(%s, %s)\n", call->callType, call->callToken); - ret|= ooCallAddG729Capability(call, OO_G729, txframes, 24, + ret|= ooCallAddG729Capability(call, OO_G729B, txframes, txframes, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); + } if(format & AST_FORMAT_G723_1) @@ -229,7 +494,7 @@ if(gH323Debug) ast_verbose("\tAdding g7231 capability to call (%s, %s)\n", call->callType, call->callToken); - ret = ooCallAddG7231Capability(call, OO_G7231, 4, 7, FALSE, + ret = ooCallAddG7231Capability(call, OO_G7231, 1, 1, FALSE, OORXANDTX, &ooh323c_start_receive_channel, &ooh323c_start_transmit_channel, &ooh323c_stop_receive_channel, @@ -261,6 +526,33 @@ &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); } + +#ifdef AST_FORMAT_AMRNB + if(format & AST_FORMAT_AMRNB) + { + if(gH323Debug) + ast_verbose("\tAdding AMR capability to call(%s, %s)\n", + call->callType, call->callToken); + ret = ooCallAddAMRNBCapability(call, OO_AMRNB, 4, 4, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + } +#endif +#ifdef AST_FORMAT_SPEEX + if(format & AST_FORMAT_SPEEX) + { + if(gH323Debug) + ast_verbose("\tAdding Speex capability to call(%s, %s)\n", + call->callType, call->callToken); + ret = ooCallAddSpeexCapability(call, OO_SPEEX, 4, 4, FALSE, + OORXANDTX, &ooh323c_start_receive_channel, + &ooh323c_start_transmit_channel, + &ooh323c_stop_receive_channel, + &ooh323c_stop_transmit_channel); + } +#endif } } @@ -295,9 +587,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 +601,19 @@ { int fmt=-1; fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap); - if(fmt>0) - ooh323_set_write_format(call, fmt); - else{ + if(fmt>0) { + switch (fmt) { + case AST_FORMAT_ALAW: + case AST_FORMAT_ULAW: + ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes); + break; + case AST_FORMAT_G729A: + ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10); + break; + default: + ooh323_set_write_format(call, fmt, 0); + } + }else{ ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n", call->callToken); return -1; @@ -331,6 +633,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 +667,28 @@ return AST_FORMAT_ALAW; case OO_GSMFULLRATE: return AST_FORMAT_GSM; + +#ifdef AST_FORMAT_AMRNB + case OO_AMRNB: + return AST_FORMAT_AMRNB; +#endif +#ifdef AST_FORMAT_SPEEX + case OO_SPEEX: + return AST_FORMAT_SPEEX; +#endif + case OO_G729: return AST_FORMAT_G729A; case OO_G729A: return AST_FORMAT_G729A; + case OO_G729B: + return AST_FORMAT_G729A; case OO_G7231: return AST_FORMAT_G723_1; + case OO_G726: + return AST_FORMAT_G726; + case OO_G726AAL2: + return AST_FORMAT_G726_AAL2; case OO_H263VIDEO: return AST_FORMAT_H263; default: --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooq931.h 2008-02-07 23:59:47.000000000 +0300 +++ 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); /** --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/oochannels.c 2008-06-04 21:35:29.000000000 +0400 +++ channels/ooh323c/src/oochannels.c 2009-10-18 23:34:33.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,13 +875,95 @@ } } - 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; } @@ -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; @@ -848,6 +1037,21 @@ /* Remaining message length is length - tpkt length */ len = len - 4; + if(len > MAXMSGLEN - 4) + { + OOTRACEERR4("Error: Invalid TPKT header for H225 message " + "Len = %d (%s, %s)\n", len, call->callType, + call->callToken); + ooCloseH225Connection(call); + ooFreeQ931Message(pctxt, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + /* Now read actual Q931 message body. We should make sure that we receive complete message as indicated by len. If we don't then there is something wrong. The loop below receives message, then checks whether @@ -863,18 +1067,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 +1088,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 +1130,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)); @@ -1009,18 +1213,33 @@ for remaining bytes of the message. If message is not received in 3 seconds, then we have a problem. Report an error and exit. */ + + if(len > MAXMSGLEN - 4) + { + OOTRACEERR4("Error: Invalid TPKT header length %d for H245 message (%s, %s)\n", + len, call->callType, call->callToken); + ooFreeH245Message(call, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + while(total < len) { recvLen = ooSocketRecv (call->pH245Channel->sock, message1, len-total); 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 +1254,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 +1571,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 +1581,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 +1602,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 +1923,12 @@ return OO_OK; } +int ooStopMonitorCallChannels(OOH323CallData * call) { + if (call->Monitor) + call->Monitor = FALSE; + /* if (call->cmdSock) + ooCloseCallCmdConnection(call); */ +} int ooStopMonitorCalls() { --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/errmgmt.c 2008-02-07 23:59:47.000000000 +0300 +++ 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; --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCalls.c 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooCalls.c 2009-10-13 05:33:19.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,12 @@ if (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN)) OO_SETFLAG (call->flags, OO_M_MEDIAWAITFORCONN); + + call->fsSent = FALSE; + +// 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 +182,8 @@ int ooAddCallToList(OOH323CallData *call) { + ast_mutex_lock(&callListLock); + if(!gH323ep.callList) { gH323ep.callList = call; @@ -170,6 +196,9 @@ gH323ep.callList->prev = call; gH323ep.callList = call; } + + ast_mutex_unlock(&callListLock); + return OO_OK; } @@ -180,9 +209,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 +266,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 +285,9 @@ if(call->next) call->next->prev = call->prev; } + + ast_mutex_unlock(&callListLock); + return OO_OK; } @@ -258,7 +302,7 @@ /* First clean all the logical channels, if not already cleaned. */ if(call->logicalChans) ooClearAllLogicalChannels(call); - + /* Close H.245 connection, if not already closed */ if(call->h245SessionState != OO_H245SESSION_CLOSED) ooCloseH245Connection(call); @@ -314,9 +358,24 @@ gH323ep.h323Callbacks.onCallCleared(call); } - pctxt = call->pctxt; + if (call->rtpMask) { + ast_mutex_lock(&call->rtpMask->lock); + call->rtpMask->inuse--; + ast_mutex_unlock(&call->rtpMask->lock); + if ((call->rtpMask->inuse) == 0) { + regfree(&call->rtpMask->regex); + ast_mutex_destroy(&call->rtpMask->lock); + free(call->rtpMask); + } + } + + pctxt = call->msgctxt; freeContext(pctxt); - ASN1CRTFREE0(pctxt); + free(pctxt); + call->msgctxt = NULL; +/* May !!!! Fix it !! */ + /* free(pctxt); */ + return OO_OK; } @@ -489,6 +548,44 @@ /* 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 ooCallAddSpeexCapability(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, @@ -596,6 +693,16 @@ return ooCapabilityDisableDTMFRFC2833(call); } +int ooCallEnableDTMFCISCO(OOH323CallData *call, int dynamicRTPPayloadType) +{ + return ooCapabilityEnableDTMFCISCO(call, dynamicRTPPayloadType); +} + +int ooCallDisableDTMFCISCO(OOH323CallData *call) +{ + return ooCapabilityDisableDTMFCISCO(call); +} + int ooCallEnableDTMFH245Alphanumeric(OOH323CallData *call) { @@ -628,7 +735,7 @@ } -OOH323CallData* ooFindCallByToken(char *callToken) +OOH323CallData* ooFindCallByToken(const char *callToken) { OOH323CallData *call; if(!callToken) @@ -636,9 +743,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 +764,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 +867,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; } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCmdChannel.h 2008-06-04 21:35:29.000000000 +0400 +++ 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*); /** --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCommon.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooCommon.h 2009-07-31 00:30:57.000000000 +0400 @@ -41,6 +41,7 @@ #include #include #endif +#include /** * @ingroup cruntime C Runtime Common Constant and Type Definitions. --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooasn1.h 2008-02-07 23:59:47.000000000 +0300 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/memheap.c 2008-02-07 23:59:47.000000000 +0300 +++ 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; } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/rtctype.c 2008-02-07 23:59:47.000000000 +0300 +++ 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" --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooStackCmds.h 2008-02-07 23:59:47.000000000 +0300 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCapability.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooCapability.h 2009-10-13 05:33:19.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, @@ -54,7 +60,11 @@ OO_GSMENHANCEDFULLRATE = 20, OO_GENERICAUDIO = 21, OO_G729EXT = 22, +#if 0 OO_AUDIO_VBD = 23, +#else + OO_SPEEX = 23, +#endif OO_AUDIOTELEPHONYEVENT = 24, OO_AUDIO_TONE = 25, OO_EXTELEM1 = 26, @@ -65,7 +75,8 @@ OO_H263VIDEO = 31, OO_IS11172VIDEO = 32, /* mpeg */ OO_GENERICVIDEO = 33, - OO_EXTELEMVIDEO = 34 + OO_EXTELEMVIDEO = 34, + OO_T38 = 35 } OOCapabilities; @@ -74,6 +85,7 @@ #define OO_CAP_DTMF_Q931 (1<<1) #define OO_CAP_DTMF_H245_alphanumeric (1<<2) #define OO_CAP_DTMF_H245_signal (1<<3) +#define OO_CAP_DTMF_CISCO (1<<4) /** * This structure defines the preference order for capabilities. @@ -548,7 +560,7 @@ * @return Pointer to the created DTMF capability, NULL in case of * failure. */ -void * ooCapabilityCreateDTMFCapability(int cap, OOCTXT *pctxt); +void * ooCapabilityCreateDTMFCapability(int cap, int dtmfcodec, OOCTXT *pctxt); /** @@ -579,6 +591,8 @@ */ struct H245AudioCapability* ooCapabilityCreateSimpleCapability (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir); +struct H245AudioCapability* ooCapabilityCreateNonStandardCapability + (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir); /** @@ -651,6 +665,10 @@ ooH323EpCapability* ooIsDataTypeSupported (struct OOH323CallData *call, H245DataType *data, int dir); +/* fill t.38 application data */ +H245DataMode_application* ooCreateT38ApplicationData + (OOCTXT* pctxt, H245DataMode_application *app); + /** * This function is used to clear the capability preference order. * @param call Handle to call, if capability preference order for call @@ -714,6 +732,9 @@ EXTERN const char* ooGetCapTypeText (OOCapabilities cap); +EXTERN int epCapIsPreferred(struct OOH323CallData *call, ooH323EpCapability *epCap); + + /** * @} */ --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh323ep.c 2008-06-04 21:35:29.000000000 +0400 +++ channels/ooh323c/src/ooh323ep.c 2009-10-13 05:33:19.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,43 @@ 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 ooH323EpAddSpeexCapability(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, @@ -659,6 +729,16 @@ } +int ooH323EpEnableDTMFCISCO(int dynamicRTPPayloadType) +{ + return ooCapabilityEnableDTMFCISCO(NULL, dynamicRTPPayloadType); +} + +int ooH323EpDisableDTMFCISCO(void) +{ + return ooCapabilityDisableDTMFCISCO(NULL); +} + int ooH323EpEnableDTMFRFC2833(int dynamicRTPPayloadType) { return ooCapabilityEnableDTMFRFC2833(NULL, dynamicRTPPayloadType); --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooStackCmds.c 2008-02-07 23:59:47.000000000 +0300 +++ 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; } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooSocket.h 2008-02-07 23:59:47.000000000 +0300 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooUtils.c 2008-02-07 23:59:47.000000000 +0300 +++ 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) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh323.c 2008-05-28 18:45:23.000000000 +0400 +++ channels/ooh323c/src/ooh323.c 2009-10-14 23:48:37.000000000 +0400 @@ -14,6 +14,10 @@ * *****************************************************************************/ +#include +#include +#include + #include "ootypes.h" #include "ooq931.h" #include "ootrace.h" @@ -29,6 +33,196 @@ /** Global endpoint structure */ extern OOH323EndPoint gH323ep; +int ooHandleFastStart(OOH323CallData *call, H225Facility_UUIE *facility) +{ + H245OpenLogicalChannel* olc; + ASN1OCTET msgbuf[MAXMSGLEN]; + ooLogicalChannel * pChannel = NULL; + H245H2250LogicalChannelParameters * h2250lcp = NULL; + int i=0, ret=0; + + /* Handle fast-start */ + if(OO_TESTFLAG (call->flags, OO_M_FASTSTART)) + { + if(facility->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)facility->fastStart.n; i++) + { + olc = NULL; + + olc = (H245OpenLogicalChannel*)memAlloc(call->pctxt, + sizeof(H245OpenLogicalChannel)); + if(!olc) + { + OOTRACEERR3("ERROR:Memory - ooHandleFastStart - 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, facility->fastStart.elem[i].data, + facility->fastStart.elem[i].numocts); + setPERBuffer(call->pctxt, msgbuf, + facility->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")) + { + + 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) + { + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + 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); + } + + } + + if(facility->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 facility message (%s, %s)\n", + call->callType, call->callToken); + } + ret = ooH323GetIpPortFromH225TransportAddress(call, + &facility->h245Address, call->remoteIP, + &call->remoteH245Port); + if(ret != OO_OK) + { + OOTRACEERR3("Error: Unknown H245 address type in received " + "CallProceeding 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; + } + if(call->remoteH245Port != 0 && !call->pH245Channel) { + /* Create an H.245 connection. + */ + if(ooCreateH245Connection(call)== OO_FAILED) + { + OOTRACEERR3("Error: H.245 channel creation failed (%s, %s)\n", + call->callType, call->callToken); + + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + } else if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + ret =ooSendTCSandMSD(call); + if (ret != OO_OK) + return ret; + } + return OO_OK; +} int ooOnReceivedReleaseComplete(OOH323CallData *call, Q931Message *q931Msg) { @@ -93,6 +287,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 && @@ -501,6 +696,11 @@ if(ret != OO_OK) { + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } OOTRACEERR3("ERROR:Unsupported media channel address type " "(%s, %s)\n", call->callType, call->callToken); return OO_FAILED; @@ -560,6 +760,26 @@ } return OO_FAILED; } + if(call->remoteH245Port != 0 && !call->pH245Channel) { + /* Create an H.245 connection. + */ + if(ooCreateH245Connection(call)== OO_FAILED) + { + OOTRACEERR3("Error: H.245 channel creation failed (%s, %s)\n", + call->callType, call->callToken); + + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + } else if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + ret =ooSendTCSandMSD(call); + if (ret != OO_OK) + return ret; } return OO_OK; } @@ -698,6 +918,234 @@ if(ret != OO_OK) { + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + 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 && + alerting->m.h245AddressPresent) { + OOTRACEINFO3("Tunneling and h245address provided." + "Giving preference to Tunneling (%s, %s)\n", + call->callType, call->callToken); + } + else if(alerting->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 Alerting message (%s, %s)\n", + call->callType, call->callToken); + } + ret = ooH323GetIpPortFromH225TransportAddress(call, + &alerting->h245Address, call->remoteIP, + &call->remoteH245Port); + if(ret != OO_OK) + { + OOTRACEERR3("Error: Unknown H245 address type in received " + "Alerting 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; + } + if(call->remoteH245Port != 0 && !call->pH245Channel) { + /* Create an H.245 connection. + */ + if(ooCreateH245Connection(call)== OO_FAILED) + { + OOTRACEERR3("Error: H.245 channel creation failed (%s, %s)\n", + call->callType, call->callToken); + + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + } else if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + ret =ooSendTCSandMSD(call); + if (ret != OO_OK) + return ret; + } + + + 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")) + { + 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) + { + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } OOTRACEERR3("ERROR:Unsupported media channel address type " "(%s, %s)\n", call->callType, call->callToken); return OO_FAILED; @@ -727,27 +1175,27 @@ /* 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 && - alerting->m.h245AddressPresent) { + progress->m.h245AddressPresent) { OOTRACEINFO3("Tunneling and h245address provided." "Giving preference to Tunneling (%s, %s)\n", call->callType, call->callToken); } - else if(alerting->m.h245AddressPresent) + 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 Alerting message (%s, %s)\n", + "provided in Progress message (%s, %s)\n", call->callType, call->callToken); } ret = ooH323GetIpPortFromH225TransportAddress(call, - &alerting->h245Address, call->remoteIP, + &progress->h245Address, call->remoteIP, &call->remoteH245Port); if(ret != OO_OK) { OOTRACEERR3("Error: Unknown H245 address type in received " - "Alerting message (%s, %s)", call->callType, + "Progress message (%s, %s)", call->callType, call->callToken); /* Mark call for clearing */ if(call->callState < OO_CALL_CLEAR) @@ -757,7 +1205,28 @@ } return OO_FAILED; } + if(call->remoteH245Port != 0 && !call->pH245Channel) { + /* Create an H.245 connection. + */ + if(ooCreateH245Connection(call)== OO_FAILED) + { + OOTRACEERR3("Error: H.245 channel creation failed (%s, %s)\n", + call->callType, call->callToken); + + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + } else if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + ret =ooSendTCSandMSD(call); + if (ret != OO_OK) + return ret; } + return OO_OK; } @@ -920,6 +1389,11 @@ &pChannel->remoteMediaPort); if(ret != OO_OK) { + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } OOTRACEERR3("ERROR:Unsupported media channel address type " "(%s, %s)\n", call->callType, call->callToken); finishPrint(); @@ -979,7 +1453,7 @@ } } - if(call->remoteH245Port != 0) + if(call->remoteH245Port != 0 && !call->pH245Channel) { /* Create an H.245 connection. */ @@ -1056,6 +1530,7 @@ DListNode *pNode = NULL; OOTimer *pTimer=NULL; int type = q931Msg->messageType; + struct timespec ts; switch(type) { case Q931SetupMsg: /* SETUP message is received */ @@ -1065,14 +1540,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 +1558,31 @@ { 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; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 24; + ast_cond_timedwait(&call->gkWait, &call->Lock, &ts); + if (call->callState == OO_CALL_WAITING_ADMISSION) + call->callState = OO_CALL_CLEAR; + 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 +1591,7 @@ call->callType, call->callToken); ooOnReceivedCallProceeding(call, q931Msg); - ooFreeQ931Message(q931Msg); + ooFreeQ931Message(call->msgctxt, q931Msg); break; @@ -1112,11 +1599,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 +1624,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 +1653,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 +1672,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; } @@ -1329,17 +1834,33 @@ return OO_OK; } } + else if(facility->reason.t == T_H225FacilityReason_forwardedElements) + { + OOTRACEINFO3("Handling fast start in forwardedElem facility for " + "(%s, %s)\n", call->callType, call->callToken); + /*start H.245 channel*/ + ret = ooHandleFastStart(call, facility); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR: Handling transportedInformation facility message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + } else{ OOTRACEINFO3("Unhandled Facility reason type received (%s, %s)\n", call->callType, call->callToken); } } 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; @@ -1396,7 +1917,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 +2129,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 +2191,10 @@ pAlias = pAliases; while(pAlias) { + if (pAlias->value[0] == 0) { + pAlias = pAlias->next; + continue; + } pAliasEntry = (H225AliasAddress*)memAlloc(pctxt, sizeof(H225AliasAddress)); if(!pAliasEntry) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooports.c 2008-02-07 23:59:47.000000000 +0300 +++ 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; } } } } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh245.h 2008-02-07 23:59:47.000000000 +0300 +++ 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); /** --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCalls.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooCalls.h 2009-10-13 05:33:19.000000000 +0400 @@ -22,6 +22,7 @@ #include "ooLogChan.h" #include "ooCapability.h" +#include #ifdef __cplusplus extern "C" { @@ -54,6 +55,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 +72,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; /** @@ -128,6 +134,12 @@ ASN1DynOctStr *elem; } FastStartResponse; +typedef struct OOH323Regex { + regex_t regex; + int inuse; + ast_mutex_t lock; +} OOH323Regex; + /** * This structure is used to maintain all information on an active call. @@ -136,9 +148,19 @@ */ typedef struct OOH323CallData { OOCTXT *pctxt; + OOCTXT *msgctxt; + pthread_t callThread; + ast_cond_t gkWait; + ast_mutex_t Lock; + OOBOOL Monitor; + OOBOOL fsSent; + 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,9 +171,11 @@ ASN1UINT flags; OOCallState callState; OOCallClearReason callEndReason; + int q931cause; unsigned h245ConnectionAttempts; OOH245SessionState h245SessionState; int dtmfmode; + int dtmfcodec; OOMediaInfo *mediaInfo; OOCallFwdData *pCallFwdData; char localIP[20];/* Local IP address */ @@ -165,7 +189,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,7 +210,15 @@ 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 */ + struct OOH323Regex* rtpMask; + char rtpMaskStr[120]; + char lastDTMF; + ASN1UINT nextDTMFstamp; 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; @@ -859,22 +871,12 @@ (*fsElem)[k].data = pData; } - /* free the stored fast start response */ - if(pQ931msg->messageType == Q931ConnectMsg) { - for(k = 0; k < pCall->pFastStartRes->n; k ++) { - memFreePtr(pCall->pctxt, pCall->pFastStartRes->elem[k].data); - } - memFreePtr(pCall->pctxt, pCall->pFastStartRes->elem); - memFreePtr(pCall->pctxt, pCall->pFastStartRes); - pCall->pFastStartRes = NULL; - } - return ASN_OK; } /* 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, @@ -1063,7 +1065,7 @@ } - ooPrepareFastStartResponseOLC(pCall, olc, epCap, pctxt, dir); + ooBuildFastStartOLC(pCall, olc, epCap, pctxt, dir); pChannel = ooFindLogicalChannelByLogicalChannelNo (pCall, olc->forwardLogicalChannelNumber); @@ -1115,7 +1117,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 +1138,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; @@ -1190,6 +1192,35 @@ return ASN_OK; } +/* + +H225 CapSet/MS determination helper function + +*/ + +int ooSendTCSandMSD(OOH323CallData *call) +{ + int ret; + 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; + } + } + + return OO_OK; +} + /* @@ -1201,11 +1232,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 +1257,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 +1320,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 +1332,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 +1343,8 @@ return OO_FAILED; } + call->alertingTime = (H235TimeStamp) time(NULL); + q931msg->callReference = call->callReference; q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt, @@ -1320,7 +1356,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; @@ -1398,13 +1434,16 @@ vendor->vendor.t35Extension = gH323ep.t35Extension; vendor->vendor.manufacturerCode = gH323ep.manufacturerCode; - ret = ooSetFastStartResponse(call, q931msg, - &alerting->fastStart.n, &alerting->fastStart.elem); - if(ret != ASN_OK) { return ret; } - if(alerting->fastStart.n > 0) { - alerting->m.fastStartPresent = TRUE; - } - else { + if (!call->fsSent) { + ret = ooSetFastStartResponse(call, q931msg, + &alerting->fastStart.n, &alerting->fastStart.elem); + if(ret != ASN_OK) { return ret; } + if(alerting->fastStart.n > 0) { + alerting->m.fastStartPresent = TRUE; + call->fsSent = TRUE; + } else + alerting->m.fastStartPresent = FALSE; + } else { alerting->m.fastStartPresent = FALSE; } @@ -1416,22 +1455,159 @@ OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken); } - memReset(&gH323ep.msgctxt); + ooSendTCSandMSD(call); + memReset (call->msgctxt); + + return ret; +} + +int ooSendProgress(OOH323CallData *call) +{ + int ret; + H225Progress_UUIE *progress; + H225VendorIdentifier *vendor; + Q931Message *q931msg=NULL; + H225TransportAddress_ipAddress *h245IpAddr; + 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; + + if (!call->fsSent) { + 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; + call->fsSent = TRUE; + } else + progress->m.fastStartPresent = FALSE; + } else { + progress->m.fastStartPresent = FALSE; + } + + /* Add h245 listener address. Do not add H245 listener address in case + of tunneling. */ + if (/* (!OO_TESTFLAG(call->flags, OO_M_FASTSTART) || + call->remoteFastStartOLCs.count == 0) && */ + !OO_TESTFLAG (call->flags, OO_M_TUNNELING) && + !call->h245listener && ooCreateH245Listener(call) == OO_OK) + { + progress->m.h245AddressPresent = TRUE; + progress->h245Address.t = T_H225TransportAddress_ipAddress; + + h245IpAddr = (H225TransportAddress_ipAddress*) + memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress)); + if(!h245IpAddr) + { + OOTRACEERR3("Error:Memory - ooAcceptCall - h245IpAddr" + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data); + h245IpAddr->ip.numocts=4; + h245IpAddr->port = *(call->h245listenport); + progress->h245Address.u.ipAddress = h245IpAddr; + } + + OOTRACEDBGA3("Built Progress (%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); + } + + ooSendTCSandMSD(call); + memReset (call->msgctxt); return ret; } -int ooSendFacility(OOH323CallData *call) +int ooSendStartH245Facility(OOH323CallData *call) { int ret=0; Q931Message *pQ931Msg = NULL; H225Facility_UUIE *facility=NULL; - OOCTXT *pctxt = &gH323ep.msgctxt; + /* OOCTXT *pctxt = &gH323ep.msgctxt; */ + OOCTXT *pctxt = call->msgctxt; + H225TransportAddress_ipAddress *h245IpAddr; 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 @@ -1479,7 +1655,29 @@ memcpy(facility->callIdentifier.guid.data, call->callIdentifier.guid.data, call->callIdentifier.guid.numocts); - facility->reason.t = T_H225FacilityReason_transportedInformation; + facility->reason.t = T_H225FacilityReason_startH245; + + if (!call->h245listener && ooCreateH245Listener(call) != OO_OK) { + OOTRACEERR3("Error:No H245Listener, can't send startH245 facility (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; + } + + facility->m.h245AddressPresent = TRUE; + facility->h245Address.t = T_H225TransportAddress_ipAddress; + + h245IpAddr = (H225TransportAddress_ipAddress*) + memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress)); + if(!h245IpAddr) { + OOTRACEERR3("Error:Memory - ooSendFacility - h245IpAddr" + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data); + h245IpAddr->ip.numocts=4; + h245IpAddr->port = *(call->h245listenport); + facility->h245Address.u.ipAddress = h245IpAddr; + OOTRACEDBGA3("Built Facility message to send (%s, %s)\n", call->callType, call->callToken); @@ -1490,7 +1688,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 +1701,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 +1739,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 +1747,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 +1781,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 +1810,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 +1823,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); @@ -1720,23 +1933,38 @@ vendor->versionId.numocts); } - ret = ooSetFastStartResponse(call, q931msg, - &connect->fastStart.n, &connect->fastStart.elem); - if(ret != ASN_OK) { return ret; } - if(connect->fastStart.n > 0) { - connect->m.fastStartPresent = TRUE; - } - else { + if (!call->fsSent) { + ret = ooSetFastStartResponse(call, q931msg, + &connect->fastStart.n, &connect->fastStart.elem); + if(ret != ASN_OK) { return ret; } + if(connect->fastStart.n > 0) { + connect->m.fastStartPresent = TRUE; + call->fsSent = TRUE; + } else + connect->m.fastStartPresent = FALSE; + } else { connect->m.fastStartPresent = FALSE; } + /* free the stored fast start response */ + if(call->pFastStartRes) { + int k; + for(k = 0; k < call->pFastStartRes->n; k ++) { + memFreePtr(call->pctxt, call->pFastStartRes->elem[k].data); + } + memFreePtr(call->pctxt, call->pFastStartRes->elem); + memFreePtr(call->pctxt, call->pFastStartRes); + call->pFastStartRes = NULL; + } + + /* Add h245 listener address. Do not add H245 listener address in case of fast-start. */ - if ((!OO_TESTFLAG(call->flags, OO_M_FASTSTART) || - call->remoteFastStartOLCs.count == 0) && - !OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + if (/* (!OO_TESTFLAG(call->flags, OO_M_FASTSTART) || + call->remoteFastStartOLCs.count == 0) && */ + !OO_TESTFLAG (call->flags, OO_M_TUNNELING) && + !call->h245listener && ooCreateH245Listener(call) == OO_OK) { - ooCreateH245Listener(call); /* First create an H.245 listener */ connect->m.h245AddressPresent = TRUE; connect->h245Address.t = T_H225TransportAddress_ipAddress; @@ -1765,31 +1993,13 @@ 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)) - { - /* Start terminal capability exchange and master slave determination */ - ret = ooSendTermCapMsg(call); - if(ret != OO_OK) - { - OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", - call->callType, call->callToken); - return ret; - } - ret = ooSendMasterSlaveDetermination(call); - if(ret != OO_OK) - { - OOTRACEERR3("ERROR:Sending Master-slave determination message " - "(%s, %s)\n", call->callType, call->callToken); - return ret; - } - } -#endif return OO_OK; } @@ -1798,6 +2008,7 @@ OOH323CallData *fwdedCall=NULL; OOCTXT *pctxt; ooAliases *pNewAlias=NULL, *alias=NULL; + struct timespec ts; 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 +2063,42 @@ 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_cond_timedwait(&fwdedCall->gkWait, &fwdedCall->Lock, &ts); + 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 +2106,7 @@ int ret=0, i=0, irand=0; char tmp[30]="\0"; char *ip=NULL, *port = NULL; + struct timespec ts; if(!dest) { @@ -1880,7 +2119,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 +2146,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 +2183,28 @@ { /* 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); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 24; + ast_cond_timedwait(&call->gkWait, &call->Lock, &ts); + if (call->callState == OO_CALL_WAITING_ADMISSION) + call->callState = OO_CALL_CLEAR; + 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 +2233,11 @@ } return OO_FAILED; } + + if(gH323ep.h323Callbacks.onOutgoingCall) { + /* Outgoing call callback function */ + gH323ep.h323Callbacks.onOutgoingCall(call); + } ret = ooH323MakeCall_helper(call); } @@ -2012,9 +2278,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 +2291,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 +2303,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 +2331,7 @@ return OO_FAILED; } strcpy(call->calledPartyNumber, pAlias->value); - ooQ931SetCalledPartyNumberIE(q931msg, + ooQ931SetCalledPartyNumberIE(pctxt, q931msg, (const char*)call->calledPartyNumber, 1, 0); } @@ -2208,7 +2476,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 +2525,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 +2541,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 +2561,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 +2582,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 +2609,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 +2629,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 +2649,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 +2713,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 +2730,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 +2743,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 +2762,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 +2778,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 +2793,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 +2809,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 +2865,7 @@ strcpy(call->pCallFwdData->ip, ip); } - ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg); + ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg); if(ret != OO_OK) { OOTRACEERR3 @@ -2683,7 +2962,7 @@ return ret; } -int ooH323HangCall(char * callToken, OOCallClearReason reason) +int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931cause) { OOH323CallData *call; @@ -2698,19 +2977,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 +3018,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*) @@ -2762,11 +3042,11 @@ 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 +3073,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 +3102,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 +3139,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 +3161,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 +3181,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 +3234,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 +3662,11 @@ "OORequestChannelCloseAck", "OORequestChannelCloseReject", "OORequestChannelCloseRelease", - "OOEndSessionCommand" + "OOEndSessionCommand", + "OOUserInputIndication", + "OORequestModeAck", + "OORequestModeReject", + "OORequestMode" }; int idx = msgType - OO_MSGTYPE_MIN; return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText)); --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/decode.c 2008-02-07 23:59:47.000000000 +0300 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooLogChan.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooLogChan.h 2009-08-25 23:34:14.000000000 +0400 @@ -41,7 +41,8 @@ OO_LOGICAL_CHAN_UNKNOWN, OO_LOGICALCHAN_IDLE, OO_LOGICALCHAN_PROPOSED, - OO_LOGICALCHAN_ESTABLISHED + OO_LOGICALCHAN_ESTABLISHED, + OO_LOGICALCHAN_PROPOSEDFS } OOLogicalChannelState; /** --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooSocket.c 2008-07-30 07:07:14.000000000 +0400 +++ channels/ooh323c/src/ooSocket.c 2009-10-15 22:16:13.000000000 +0400 @@ -13,6 +13,9 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include +#include #include "ooSocket.h" #include "ootrace.h" @@ -270,8 +273,10 @@ if (bind (socket, (struct sockaddr *) (void*) &m_addr, sizeof (m_addr)) == -1) { - perror ("bind"); - OOTRACEERR1("Error:Bind failed\n"); + if (errno != EADDRINUSE) { + perror ("bind"); + OOTRACEERR2("Error:Bind failed, error: %d\n", errno); + } return ASN_E_INVSOCKET; } @@ -303,7 +308,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 +343,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 +449,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 +471,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 +643,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 +685,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 +708,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) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ootypes.h 2008-05-28 18:45:23.000000000 +0400 +++ 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; --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/dlist.c 2008-02-07 23:59:47.000000000 +0300 +++ 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) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooGkClient.h 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooGkClient.h 2009-08-25 23:34:14.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; @@ -411,7 +412,7 @@ /** - * This function is used to send an unregistration confirm messsage to + * This function is used to send an unregistration confirm message to * gatekeeper. * @param pGkClient Handle to gatekeeper client. * @param reqNo Request Sequence number for the confirm message. --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCmdChannel.c 2008-12-22 20:01:00.000000000 +0300 +++ 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; +} --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooTimer.c 2008-02-07 23:59:47.000000000 +0300 +++ 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" --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooLogChan.c 2008-05-28 18:45:23.000000000 +0400 +++ channels/ooh323c/src/ooLogChan.c 2009-08-05 02:16: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,27 @@ 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 && + pChannel->state != OO_LOGICALCHAN_PROPOSEDFS) + return pChannel; + else + pChannel = pChannel->next; + } + return NULL; +} + int ooClearAllLogicalChannels(OOH323CallData *call) { OOLogicalChannel * temp = NULL, *prev = NULL; --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/printHandler.c 2008-02-07 23:59:47.000000000 +0300 +++ 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" --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/encode.c 2008-02-07 23:59:47.000000000 +0300 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/context.c 2008-02-07 23:59:47.000000000 +0300 +++ 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; --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/perutil.c 2008-02-07 23:59:47.000000000 +0300 +++ 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" --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ootrace.h 2008-06-04 21:35:29.000000000 +0400 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh245.c 2008-02-07 23:59:47.000000000 +0300 +++ channels/ooh323c/src/ooh245.c 2009-10-13 23:16:06.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, *rtdCap = 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++; } } @@ -515,7 +619,7 @@ if(call->dtmfmode & OO_CAP_DTMF_RFC2833) { ateCap = (H245AudioTelephonyEventCapability*) - ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_RFC2833, pctxt); + ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_RFC2833, call->dtmfcodec, pctxt); if(!ateCap) { OOTRACEWARN3("WARN:Failed to add RFC2833 cap to TCS(%s, %s)\n", @@ -541,6 +645,44 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; + + i++; + } + } + + if(call->dtmfmode & OO_CAP_DTMF_CISCO) + { + rtdCap = (H245DataApplicationCapability*) + ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_CISCO, call->dtmfcodec, pctxt); + if(!rtdCap) + { + OOTRACEWARN3("WARN:Failed to add RTP/CISCO DTMF cap to TCS(%s, %s)\n", + call->callType, call->callToken); + } + else { + entry = (H245CapabilityTableEntry*) memAlloc(pctxt, + sizeof(H245CapabilityTableEntry)); + if(!entry) + { + OOTRACEERR3("Error:Failed to allocate memory for new capability " + "table entry. (%s, %s)\n", call->callType, + call->callToken); + ooFreeH245Message(call, ph245msg); + return OO_FAILED; + } + + memset(entry, 0, sizeof(H245CapabilityTableEntry)); + entry->m.capabilityPresent = 1; + + entry->capability.t = T_H245Capability_receiveDataApplicationCapability; + entry->capability.u.receiveDataApplicationCapability = rtdCap; + + entry->capabilityTableEntryNumber = i+1; + dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -549,7 +691,7 @@ if(call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric) { userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability - (OO_CAP_DTMF_H245_alphanumeric, pctxt); + (OO_CAP_DTMF_H245_alphanumeric, 0, pctxt); if(!userInputCap) { OOTRACEWARN3("WARN:Failed to add H245(alphanumeric) cap to " @@ -575,6 +717,8 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -583,7 +727,7 @@ if(call->dtmfmode & OO_CAP_DTMF_H245_signal) { userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability - (OO_CAP_DTMF_H245_signal, pctxt); + (OO_CAP_DTMF_H245_signal, 0, pctxt); if(!userInputCap) { OOTRACEWARN3("WARN:Failed to add H245(signal) cap to " @@ -609,6 +753,8 @@ entry->capabilityTableEntryNumber = i+1; dListAppend(pctxt , &(termCap->capabilityTable), entry); + altSetDtmf->elem[altSetDtmf->n] = i+1; + altSetDtmf->n++; i++; } @@ -636,7 +782,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 +845,7 @@ { H245MasterSlaveDetermination *masterSlave; H245MasterSlaveDeterminationAck *masterSlaveAck; - ASN1UINT statusDeterminationNumber; + ASN1UINT statusDeterminationNumber, moduloDiff; switch(msgType) { @@ -704,7 +854,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 +889,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 +907,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 +917,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 +948,8 @@ call->callType, call->callToken); } } + + call->msAckStatus = OO_msAck_remoteReceived; if(call->localTermCapState == OO_LocalTermCapSetAckRecvd && call->remoteTermCapState == OO_RemoteTermCapSetAckSent) @@ -788,7 +958,7 @@ if(gH323ep.h323Callbacks.openLogicalChannels) gH323ep.h323Callbacks.openLogicalChannels(call); else{ - if(!call->logicalChans) + if(!ooGetTransmitLogicalChannel(call)) ooOpenLogicalChannels(call); } #if 0 @@ -816,7 +986,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 +998,7 @@ return OO_OK; } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -873,9 +1044,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 +1082,7 @@ } ooFreeH245Message(call, ph245msg); + call->msAckStatus = OO_msAck_localSent; return ret; } @@ -918,10 +1091,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 +1137,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 +1203,259 @@ 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,&(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 +1490,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 +1590,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 +1605,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 +1715,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" @@ -1346,12 +1770,14 @@ H245OpenLogicalChannelAck *olcAck) { char remoteip[20]; + regmatch_t pmatch[1]; + int i; ooLogicalChannel *pLogicalChannel; H245H2250LogicalChannelAckParameters *h2250lcap; H245UnicastAddress *unicastAddr; H245UnicastAddress_iPAddress *iPAddress; H245UnicastAddress *unicastAddr1; - H245UnicastAddress_iPAddress *iPAddress1; + H245UnicastAddress_iPAddress *iPAddress1 = NULL; if(!((olcAck->m.forwardMultiplexAckParametersPresent == 1) && (olcAck->forwardMultiplexAckParameters.t == @@ -1396,30 +1822,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); @@ -1440,9 +1865,19 @@ pLogicalChannel->sessionID = h2250lcap->sessionID; /* Populate ports &ip for channel */ + + if (call->rtpMaskStr[0]) { + if (regexec(&call->rtpMask->regex, remoteip, 1, pmatch, 0)) { + OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s" + "(%s, %s)\n", remoteip, call->rtpMaskStr, call->callType, call->callToken); + return OO_FAILED; + } + } + strcpy(pLogicalChannel->remoteIP, remoteip); pLogicalChannel->remoteMediaPort = iPAddress->tsapIdentifier; - pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier; + if (iPAddress1) + pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier; if(pLogicalChannel->chanCap->startTransmitChannel) { @@ -1567,7 +2002,7 @@ H245CommandMessage * command; OOCTXT *pctxt; H245Message *ph245msg=NULL; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_command); if(ret != OO_OK) { @@ -1578,7 +2013,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,13 +2111,14 @@ 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); else{ - if(!call->logicalChans) + if(!ooGetTransmitLogicalChannel(call)) ooOpenLogicalChannels(call); } #if 0 @@ -1697,14 +2134,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 +2166,7 @@ H245RequestMessage *request; H245CloseLogicalChannel* clc; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -1738,7 +2176,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 +2234,7 @@ H245RequestMessage *request; H245RequestChannelClose *rclc; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -1806,7 +2245,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 +2288,7 @@ OOCTXT *pctxt; H245IndicationMessage *indication; - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_indication); if(ret != OO_OK) { @@ -1859,7 +2299,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 +2360,7 @@ return OO_FAILED; } } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -1927,7 +2368,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 +2497,7 @@ return OO_FAILED; } - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_response); if(ret != OO_OK) { @@ -2064,7 +2506,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 +2587,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 +2708,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++) { @@ -2319,6 +2787,8 @@ } ooOnReceivedCloseChannelAck(call, response->u.closeLogicalChannelAck); + if(!ooGetTransmitLogicalChannel(call)) + ooOpenLogicalChannels(call); break; case T_H245ResponseMessage_requestChannelCloseAck: OOTRACEINFO4("RequestChannelCloseAck received - %d (%s, %s)\n", @@ -2408,6 +2878,24 @@ } else if((indication->t == T_H245UserInputIndication_signal) && (call->dtmfmode & OO_CAP_DTMF_H245_signal)) { + if(call->lastDTMF && indication->u.signal->signalType[0] == call->lastDTMF && + call->nextDTMFstamp && indication->u.signal->m.rtpPresent && + indication->u.signal->rtp.m.timestampPresent) { + if(call->nextDTMFstamp > indication->u.signal->rtp.timestamp) { + OOTRACEERR4("ERROR:Duplicate dtmf %c on ((%s, %s)\n", call->lastDTMF, call->callType, + call->callToken); + return OO_OK; + } + } + if (indication->u.signal->m.rtpPresent && indication->u.signal->rtp.m.timestampPresent && + indication->u.signal->m.durationPresent) { + call->nextDTMFstamp = indication->u.signal->rtp.timestamp + + indication->u.signal->duration; + call->lastDTMF = indication->u.signal->signalType[0]; + } else { + call->nextDTMFstamp = 0; + call->lastDTMF = 0; + } if(gH323ep.h323Callbacks.onReceivedDTMF) gH323ep.h323Callbacks.onReceivedDTMF(call, indication->u.signal->signalType); @@ -2427,7 +2915,7 @@ H245CapabilityTableEntry *capEntry = NULL; tcs = pmsg->h245Msg.u.request->u.terminalCapabilitySet; - if(call->remoteTermCapSeqNo >= tcs->sequenceNumber) + if(call->remoteTermCapSeqNo > tcs->sequenceNumber) { OOTRACEINFO4("Rejecting TermCapSet message with SeqNo %d, as already " "acknowledged message with this SeqNo (%s, %s)\n", @@ -2435,6 +2923,16 @@ ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, T_H245TerminalCapabilitySetReject_cause_unspecified); return OO_OK; + + } else { +/* 20090924 */ +/* bogus soft-switch can send more than one request with cap set + if it goto to next choice. Right swith don't send but not all are right ;( + we can accept new capability set only. We must remember also that new join caps + will be previously joined caps with new cap set. + */ + if(call->remoteTermCapSeqNo == tcs->sequenceNumber) + call->localTermCapState = OO_LocalTermCapExchange_Idle; } if(!tcs->m.capabilityTablePresent) @@ -2474,6 +2972,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; @@ -2507,7 +3009,7 @@ if(gH323ep.h323Callbacks.openLogicalChannels) gH323ep.h323Callbacks.openLogicalChannels(call); else{ - if(!call->logicalChans) + if(!ooGetTransmitLogicalChannel(call)) ooOpenLogicalChannels(call); } #if 0 @@ -2527,7 +3029,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 +3040,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 +3073,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 +3084,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 +3116,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 +3167,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 +3227,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 +3295,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 +3366,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++) @@ -2899,7 +3406,7 @@ } } - else if(call->masterSlaveState == OO_MasterSlave_Slave) + else { epCap = call->jointCaps; @@ -2924,17 +3431,22 @@ case OO_G711ALAW56K: case OO_G711ULAW64K: case OO_G711ULAW56K: - /*case OO_G726:*/ + case OO_G726: + case OO_G726AAL2: + case OO_AMRNB: + case OO_SPEEX: 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 +3465,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 +3476,7 @@ ooGetCapTypeText(epCap->cap), call->callType, call->callToken); - ret = ooCreateH245Message(&ph245msg, + ret = ooCreateH245Message(call, &ph245msg, T_H245MultimediaSystemControlMessage_request); if(ret != OO_OK) { @@ -2980,7 +3493,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 +3567,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 +3635,7 @@ } ooFreeH245Message(call, ph245msg); - return ret; + return ret; } @@ -3362,7 +3893,7 @@ else { /* Calling other ep, with SETUP message */ /* Call is "outgoing */ - pLogicalChannel->state = OO_LOGICALCHAN_PROPOSED; + pLogicalChannel->state = OO_LOGICALCHAN_PROPOSEDFS; } return OO_OK; @@ -3447,13 +3978,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) @@ -3507,6 +4045,8 @@ { H245UnicastAddress *unicastAddress = NULL; H245UnicastAddress_iPAddress *ipAddress = NULL; + int i; + regmatch_t pmatch[1]; if(h245Address->t != T_H245TransportAddress_unicastAddress) { @@ -3530,6 +4070,14 @@ ipAddress->network.data[1], ipAddress->network.data[2], ipAddress->network.data[3]); + if (call->rtpMaskStr[0]) { + if (regexec(&call->rtpMask->regex, ip, 1, pmatch, 0)) { + OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s" + "(%s, %s)\n", ip, call->rtpMaskStr, call->callType, call->callToken); + return OO_FAILED; + } + } + return OO_OK; } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh323.h 2008-02-07 23:59:47.000000000 +0300 +++ 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. --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ootrace.c 2008-06-04 21:35:29.000000000 +0400 +++ 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); } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/eventHandler.c 2008-02-07 23:59:47.000000000 +0300 +++ 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) --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooh323ep.h 2008-06-04 21:35:29.000000000 +0400 +++ 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 --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooGkClient.c 2008-05-28 18:45:23.000000000 +0400 +++ channels/ooh323c/src/ooGkClient.c 2009-08-25 23:34:15.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_signal(&pCallAdmInfo->call->gkWait); + /* ooH323CallAdmitted( pCallAdmInfo->call); */ + dListRemove(&pGkClient->callsPendingList, pNode); dListAppend(&pGkClient->ctxt, &pGkClient->callsAdmittedList, pNode->data); @@ -1874,9 +1975,10 @@ (ooGkClient *pGkClient, H225AdmissionReject *pAdmissionReject) { RasCallAdmissionInfo* pCallAdmInfo=NULL; - unsigned int x; - DListNode *pNode=NULL; + unsigned int x, y; + DListNode *pNode=NULL, *pNode1=NULL; OOH323CallData *call=NULL; + OOTimer *pTimer = NULL; /* Search call in pending calls list */ for(x=0 ; xcallsPendingList.count; x++) @@ -1903,6 +2005,24 @@ memFreePtr(&pGkClient->ctxt, pNode); } + /* Delete ARQ timer */ + for(y=0; ytimerList.count; y++) + { + pNode1 = dListFindByIndex(&pGkClient->timerList, y); + pTimer = (OOTimer*)pNode1->data; + if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_ARQ_TIMER) + { + if(((ooGkClientTimerCb*)pTimer->cbData)->pAdmInfo == + pCallAdmInfo) + { + memFreePtr(&pGkClient->ctxt, pTimer->cbData); + ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, + pTimer); + OOTRACEDBGA1("Deleted ARQ Timer.\n"); + break; + } + } + } OOTRACEINFO4("Admission Reject message received with reason code %d for " "(%s, %s)\n", pAdmissionReject->rejectReason.t, call->callType, call->callToken); @@ -1948,9 +2068,272 @@ break; } + ast_cond_signal(&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 +2353,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 +2363,7 @@ { OOTRACEERR1("Error: Memory allocation for DRQ RAS message failed\n"); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } @@ -1989,6 +2375,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 +2396,7 @@ "message.\n"); memReset(pctxt); pGkClient->state = GkClientFailed; + ast_mutex_unlock(&pGkClient->Lock); return OO_FAILED; } memcpy((void*)pDRQ->endpointIdentifier.data, @@ -2040,6 +2428,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 +2444,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 +2491,7 @@ break; } } + ast_mutex_unlock(&pGkClient->Lock); return iRet; } @@ -2174,6 +2583,9 @@ OOTRACEDBGA1("Gatekeeper client ARQ timer expired.\n"); memFreePtr(&pGkClient->ctxt, cbData); + if(!pAdmInfo) + return OO_OK; + if(pAdmInfo->retries < OO_MAX_ARQ_RETRIES) { ret = ooGkClientSendAdmissionRequest(pGkClient, pAdmInfo->call, TRUE); @@ -2199,6 +2611,8 @@ ooGkClientTimerCb *cbData=NULL; RasCallAdmissionInfo *pAdmInfo = NULL; + ast_mutex_lock(&pGkClient->Lock); + for(x=0; xcallsAdmittedList.count; x++) { @@ -2209,7 +2623,7 @@ dListRemove(&pGkClient->callsAdmittedList, pNode); memFreePtr(&pGkClient->ctxt, pAdmInfo); memFreePtr(&pGkClient->ctxt, pNode); - return OO_OK; + break; } } @@ -2237,10 +2651,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; } --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/memheap.h 2008-02-07 23:59:47.000000000 +0300 +++ 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 */ --- ../bb/asterisk-addons-1.6.1.0/channels/ooh323c/src/ooCapability.c 2008-06-04 21:35:29.000000000 +0400 +++ channels/ooh323c/src/ooCapability.c 2009-10-13 05:33:19.000000000 +0400 @@ -13,6 +13,9 @@ * maintain this copyright notice. * *****************************************************************************/ +#include +#include + #include "ooCapability.h" #include "ootrace.h" #include "ooCalls.h" @@ -22,6 +25,7 @@ extern OOH323EndPoint gH323ep; static int giDynamicRTPPayloadType = 101; +static int gcDynamicRTPPayloadType = 121; int ooCapabilityEnableDTMFRFC2833 (OOH323CallData *call, int dynamicRTPPayloadType) @@ -30,16 +34,47 @@ { gH323ep.dtmfmode |= OO_CAP_DTMF_RFC2833; OOTRACEINFO1("Enabled RFC2833 DTMF capability for end-point\n"); + /*Dynamic RTP payload type range is from 96 - 127 */ + if(dynamicRTPPayloadType >= 96 && dynamicRTPPayloadType <= 127) + giDynamicRTPPayloadType = dynamicRTPPayloadType; } else{ call->dtmfmode |= OO_CAP_DTMF_RFC2833; OOTRACEINFO3("Enabled RFC2833 DTMF capability for (%s, %s) \n", call->callType, call->callToken); + if(dynamicRTPPayloadType >= 96 && dynamicRTPPayloadType <= 127) + call->dtmfcodec = dynamicRTPPayloadType; + else + call->dtmfcodec = giDynamicRTPPayloadType; } - /*Dynamic RTP payload type range is from 96 - 127 */ + + return OO_OK; +} + +int ooCapabilityEnableDTMFCISCO + (OOH323CallData *call, int dynamicRTPPayloadType) +{ + if(!call) + { + gH323ep.dtmfmode |= OO_CAP_DTMF_CISCO; + OOTRACEINFO1("Enabled RTP/CISCO DTMF capability for end-point\n"); + /*Dynamic RTP payload type range is from 96 - 127 */ + if(dynamicRTPPayloadType >= 96 && dynamicRTPPayloadType <= 127) + gcDynamicRTPPayloadType = dynamicRTPPayloadType; + else + call->dtmfcodec = dynamicRTPPayloadType; + } + else{ + call->dtmfmode |= OO_CAP_DTMF_CISCO; + OOTRACEINFO3("Enabled RTP/CISCO DTMF capability for (%s, %s) \n", + call->callType, call->callToken); if(dynamicRTPPayloadType >= 96 && dynamicRTPPayloadType <= 127) - giDynamicRTPPayloadType = dynamicRTPPayloadType; + call->dtmfcodec = dynamicRTPPayloadType; + else + call->dtmfcodec = gcDynamicRTPPayloadType; + } + return OO_OK; } @@ -61,6 +96,21 @@ return OO_OK; } +int ooCapabilityDisableDTMFCISCO(OOH323CallData *call) +{ + if(!call){ + gH323ep.dtmfmode ^= OO_CAP_DTMF_CISCO; + OOTRACEINFO1("Disabled RTP/CISCO DTMF capability for end-point\n"); + } + else{ + call->dtmfmode ^= OO_CAP_DTMF_CISCO; + OOTRACEINFO3("Disabled RTP/CISCO DTMF capability for (%s, %s)\n", + call->callType, call->callToken); + } + + return OO_OK; +} + int ooCapabilityEnableDTMFH245Alphanumeric(OOH323CallData *call) { if(!call){ @@ -335,8 +385,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 +498,20 @@ 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; + } + return 0; +} int ooCapabilityAddGSMCapability(OOH323CallData *call, int cap, unsigned framesPerPkt, OOBOOL comfortNoise, @@ -544,6 +607,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 +766,19 @@ 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: + case OO_SPEEX: + return ooCapabilityCreateNonStandardCapability(epCap, pctxt, dir); + case OO_GSMHALFRATE: + case OO_GSMENHANCEDFULLRATE: case OO_GSMFULLRATE: return ooCapabilityCreateGSMFullRateCapability(epCap, pctxt, dir); default: @@ -626,9 +790,10 @@ -void* ooCapabilityCreateDTMFCapability(int cap, OOCTXT *pctxt) +void* ooCapabilityCreateDTMFCapability(int cap, int dtmfcodec, OOCTXT *pctxt) { H245AudioTelephonyEventCapability *pATECap=NULL; + H245DataApplicationCapability *pCSDTMFCap=NULL; H245UserInputCapability *userInput = NULL; char *events=NULL; switch(cap) @@ -642,8 +807,9 @@ return NULL; } memset(pATECap, 0, sizeof(H245AudioTelephonyEventCapability)); - pATECap->dynamicRTPPayloadType = giDynamicRTPPayloadType; + pATECap->dynamicRTPPayloadType = dtmfcodec; events = (char*)memAlloc(pctxt, strlen("0-16")+1); + memset(events, 0, strlen("0-16")+1); if(!events) { OOTRACEERR1("Error:Memory - ooCapabilityCreateDTMFCapability - events\n"); @@ -653,6 +819,40 @@ strncpy(events, "0-16", strlen("0-16")); pATECap->audioTelephoneEvent = events; return pATECap; + case OO_CAP_DTMF_CISCO: + pCSDTMFCap = (H245DataApplicationCapability*)memAlloc(pctxt, + sizeof(H245DataApplicationCapability)); + if(!pCSDTMFCap) + { + OOTRACEERR1("Error:Memory - ooCapabilityCreateDTMFCapability - pCSDTMFCap\n"); + return NULL; + } + memset(pCSDTMFCap, 0, sizeof(H245DataApplicationCapability)); + pCSDTMFCap->application.t = T_H245DataApplicationCapability_application_nonStandard; + if ( (pCSDTMFCap->application.u.nonStandard = (H245NonStandardParameter *) + memAllocZ(pctxt, sizeof(H245NonStandardParameter))) == NULL) { + OOTRACEERR1("Error:Memory-ooCapabilityCreateDTMFCapability-H245NonStandardParameter\n"); + memFreePtr(pctxt, pCSDTMFCap); + return NULL; + } + + pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.t=T_H245NonStandardIdentifier_h221NonStandard; + pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.u.h221NonStandard = + (H245NonStandardIdentifier_h221NonStandard *) memAllocZ(pctxt, + sizeof(H245NonStandardIdentifier_h221NonStandard)); + if (!pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.u.h221NonStandard) { + OOTRACEERR1("Error:Memory-ooCapabilityCreateDTMFCapability-H245NonStandardParameter\n"); + memFreePtr(pctxt, pCSDTMFCap); + return NULL; + } + + pCSDTMFCap->application.u.nonStandard->data.data = "RtpDtmfRelay"; + pCSDTMFCap->application.u.nonStandard->data.numocts = sizeof("RtpDtmfRelay")-1; + pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35CountryCode = 181; + pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35Extension = 0; + pCSDTMFCap->application.u.nonStandard->nonStandardIdentifier.u.h221NonStandard->manufacturerCode = 18; + + return pCSDTMFCap; case OO_CAP_DTMF_H245_alphanumeric: userInput = (H245UserInputCapability*)memAllocZ(pctxt, sizeof(H245UserInputCapability)); @@ -774,8 +974,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 +1048,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 +1069,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 +1099,171 @@ } return NULL; } +/* This is used for g726, AMRNB, Speex */ +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: + case OO_SPEEX: + 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; + break; + + case OO_SPEEX: + pAudio->u.nonStandard->data.data = "Speex"; + pAudio->u.nonStandard->data.numocts = sizeof("Speex")-1; + /* Equivalence OpenH323 SpeexNB */ + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35CountryCode = 9; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->t35Extension = 0; + pAudio->u.nonStandard->nonStandardIdentifier.u.h221NonStandard->manufacturerCode = 61; + + break; + } + return pAudio; + + default: + OOTRACEERR2("ERROR: Don't know how to create audio capability %d\n", + epCap->cap); + } + return NULL; +} + +/* Our t.38 params */ + +struct H245DataMode_application* ooCreateT38ApplicationData + (OOCTXT* pctxt, H245DataMode_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 +1308,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 +1356,57 @@ 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: /* case sizeof("Speex")-1 */ + if (!strncmp(audioCap->u.nonStandard->data.data, "AMRNB", + audioCap->u.nonStandard->data.numocts)) + cap = OO_AMRNB; + else if (!strncmp(audioCap->u.nonStandard->data.data, "Speex", + audioCap->u.nonStandard->data.numocts)) + cap = OO_SPEEX; + 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 +1432,8 @@ return FALSE; } + if(cap != epCap->cap) { return FALSE; } + /* can we receive this capability */ if(dir & OORX) { @@ -1026,6 +1457,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 +1652,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 +1679,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 +1704,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 +1737,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 +1942,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; } @@ -1526,7 +1988,9 @@ { if(((OOCapParams*)cur->params)->rxframes < framesPerPkt) return NULL; - else{ + if(((OOCapParams*)cur->params)->rxframes > framesPerPkt) + ((OOCapParams*)cur->params)->rxframes = framesPerPkt; + OOTRACEDBGC4("We can receive Simple capability %s. (%s, %s)\n", ooGetCapTypeText(cur->cap), call->callType, call->callToken); @@ -1555,7 +2019,6 @@ ooGetCapTypeText(cur->cap), call->callType, call->callToken); return epCap; - } } /* Can we transmit compatible stream */ @@ -1601,6 +2064,145 @@ 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: /* sizeof("Speex") */ + if (!strncmp(audioCap->u.nonStandard->data.data, "AMRNB", + audioCap->u.nonStandard->data.numocts)) + cap = OO_AMRNB; + else if (!strncmp(audioCap->u.nonStandard->data.data, "Speex", + audioCap->u.nonStandard->data.numocts)) + cap = OO_SPEEX; + 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 +2219,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 +2233,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 +2537,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 +2669,6 @@ return OO_OK; } - int ooAddRemoteCapability(OOH323CallData *call, H245Capability *cap) { switch(cap->t) @@ -1972,6 +2682,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 +2702,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 +2774,44 @@ 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); + + if (audioCap->u.nonStandard && + audioCap->u.nonStandard->nonStandardIdentifier.t == + T_H245NonStandardIdentifier_h221NonStandard && + audioCap->u.nonStandard->data.numocts == sizeof("Speex")-1 && + !strncmp(audioCap->u.nonStandard->data.data, "Speex", + audioCap->u.nonStandard->data.numocts)) + return ooCapabilityAddSimpleCapability(call, OO_SPEEX, 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 +2842,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 +2889,6 @@ return OO_OK; } - - - - int ooCapabilityUpdateJointCapabilities (OOH323CallData* call, H245Capability *cap) { @@ -2123,7 +2907,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 +2917,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 +3112,7 @@ { static const char *capTypes[]={ "unknown", - "OO_NONSTANDARD", + "OO_G726", "OO_G711ALAW64K", "OO_G711ALAW56K", "OO_G711ULAW64K", @@ -2322,8 +3124,8 @@ "OO_G728", "OO_G729", "OO_G729ANNEXA", - "OO_IS11172AUDIO", - "OO_IS13818AUDIO", + "OO_AMRNB", + "OO_G726AAL2", "OO_G729WANNEXB", "OO_G729ANNEXAWANNEXB", "OO_G7231ANNEXC", @@ -2332,7 +3134,7 @@ "OO_GSMENHANCEDFULLRATE", "OO_GENERICAUDIO", "OO_G729EXTENSIONS", - "OO_VBD", + "OO_SPEEX", "OO_AUDIOTELEPHONYEVENT", "OO_AUDIOTONE", "OO_EXTELEM1", @@ -2343,7 +3145,8 @@ "OO_H263VIDEO", "OO_IS11172VIDEO", /* mpeg */ "OO_GENERICVIDEO", - "OO_EXTELEMVIDEO" + "OO_EXTELEMVIDEO", + "OO_T38" /* T.38 */ }; return ooUtilsGetText (cap, capTypes, OONUMBEROF(capTypes)); }