diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index 7724c21d444f2ce583ca34c092716dcdeffab4ed..2ae95fae44fe3c2155cd913a76da41acdce55217 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -187,6 +187,7 @@ static struct ooh323_pvt { struct ast_dsp *vad; struct OOH323Regex *rtpmask; /* rtp ip regexp */ char rtpmaskstr[120]; + int rtdrcount, rtdrinterval; /* roundtripdelayreq */ struct ooh323_pvt *next; /* Next entity */ } *iflist = NULL; @@ -212,6 +213,7 @@ struct ooh323_user{ char mIP[20]; struct OOH323Regex *rtpmask; char rtpmaskstr[120]; + int rtdrcount, rtdrinterval; struct ooh323_user *next; }; @@ -238,6 +240,7 @@ struct ooh323_peer{ int rtptimeout; struct OOH323Regex *rtpmask; char rtpmaskstr[120]; + int rtdrcount,rtdrinterval; struct ooh323_peer *next; }; @@ -302,6 +305,7 @@ static int gIncomingLimit = 1024; static int gOutgoingLimit = 1024; OOBOOL gH323Debug = FALSE; static int gTRCLVL = OOTRCLVLERR; +static int gRTDRCount = 0, gRTDRInterval = 0; static int t35countrycode = 0; static int t35extensions = 0; @@ -502,6 +506,8 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) pvt->faxmode = 0; pvt->t38support = gT38Support; pvt->rtptimeout = gRTPTimeout; + pvt->rtdrinterval = gRTDRInterval; + pvt->rtdrcount = gRTDRCount; pvt->call_reference = callref; if (callToken) @@ -627,6 +633,12 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, p->rtpmask = peer->rtpmask; ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr)); } + + if (peer->rtdrinterval) { + p->rtdrinterval = peer->rtdrinterval; + p->rtdrcount = peer->rtdrcount; + } + ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode)); p->amaflags = peer->amaflags; } else { @@ -635,6 +647,8 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, p->t38support = gT38Support; p->rtptimeout = gRTPTimeout; p->capability = gCapability; + p->rtdrinterval = gRTDRInterval; + p->rtdrcount = gRTDRCount; memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref)); p->username = strdup(dest); @@ -1721,6 +1735,10 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg) ast_copy_string(p->rtpmaskstr, user->rtpmaskstr, sizeof(p->rtpmaskstr)); } + if (user->rtdrcount > 0 && user->rtdrinterval > 0) { + p->rtdrcount = user->rtdrcount; + p->rtdrinterval = user->rtdrinterval; + } if (user->incominglimit) user->inUse++; ast_mutex_unlock(&user->lock); } else { @@ -2129,6 +2147,8 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) } else if (!strcasecmp(v->name, "accountcode")) { strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1); + } else if (!strcasecmp(v->name, "roundtrip")) { + sscanf(v->value, "%d,%d", &user->rtdrcount, &user->rtdrinterval); } else if (!strcasecmp(v->name, "rtptimeout")) { user->rtptimeout = atoi(v->value); if (user->rtptimeout < 0) @@ -2288,6 +2308,8 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, tcodecs, 1); } else if (!strcasecmp(v->name, "amaflags")) { peer->amaflags = ast_cdr_amaflags2int(v->value); + } else if (!strcasecmp(v->name, "roundtrip")) { + sscanf(v->value, "%d,%d", &peer->rtdrcount, &peer->rtdrinterval); } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "rfc2833")) peer->dtmfmode = H323_DTMF_RFC2833; @@ -2431,6 +2453,8 @@ int reload_config(int reload) gRasGkMode = RasNoGatekeeper; gGatekeeper[0] = '\0'; gRTPTimeout = 60; + gRTDRInterval = 0; + gRTDRCount = 0; strcpy(gAccountcode, DEFAULT_H323ACCNT); gFastStart = 1; gTunneling = 1; @@ -2488,6 +2512,8 @@ int reload_config(int reload) ooH323EpEnableH245Tunneling(); else ooH323EpDisableH245Tunneling(); + } else if (!strcasecmp(v->name, "roundtrip")) { + sscanf(v->value, "%d,%d", &gRTDRCount, &gRTDRInterval); } else if (!strcasecmp(v->name, "trybemaster")) { gBeMaster = ast_true(v->value); if (gBeMaster) @@ -2757,6 +2783,8 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc 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); + if (peer->rtdrcount && peer->rtdrinterval) + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval); ast_mutex_unlock(&peer->lock); } else { ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); @@ -2900,6 +2928,8 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc if (user->rtpmaskstr[0]) ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); ast_mutex_unlock(&user->lock); + if (user->rtdrcount && user->rtdrinterval) + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval); } else { ast_cli(a->fd, "User %s not found\n", a->argv[3]); ast_cli(a->fd, "\n"); @@ -3066,6 +3096,9 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str else if (gT38Support == T38_FAXGW) ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + if (gRTDRCount && gRTDRInterval) + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval); + ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); @@ -3811,6 +3844,13 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call) } + if (p->rtdrcount) { + if (gH323Debug) + ast_verbose("Setup RTDR info: %d, %d\n", p->rtdrinterval, p->rtdrcount); + call->rtdrInterval = p->rtdrinterval; + call->rtdrCount = p->rtdrcount; + } + ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP)); mediaInfo.lMediaPort = ntohs(us.sin_port); diff --git a/addons/ooh323c/src/ooCalls.h b/addons/ooh323c/src/ooCalls.h index 68dd3bfbd37fdb0d80ef1d98333fe893a4ff1587..05494296ee2fe044959c3723312616c0bdd4cdf5 100644 --- a/addons/ooh323c/src/ooCalls.h +++ b/addons/ooh323c/src/ooCalls.h @@ -219,6 +219,8 @@ typedef struct OOH323CallData { char rtpMaskStr[120]; char lastDTMF; ASN1UINT nextDTMFstamp; + int rtdrInterval, rtdrCount; /* roundTripDelay interval and unreplied count */ + ASN1UINT rtdrSend, rtdrRecv; /* last sended/replied RTD request */ void *usrData; /*!<User can set this to user specific data*/ struct OOH323CallData* next; struct OOH323CallData* prev; diff --git a/addons/ooh323c/src/ooSocket.c b/addons/ooh323c/src/ooSocket.c index 590536550742dcdcdf77e84ad3db9839ad1c835e..7c1b000a4376b46eeb45f4dd9f0ca888b792c533 100644 --- a/addons/ooh323c/src/ooSocket.c +++ b/addons/ooh323c/src/ooSocket.c @@ -611,6 +611,7 @@ int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList) struct ifconf ifc; int ifNum; OOInterface *pIf=NULL; + struct sockaddr_in sin; OOTRACEDBGA1("Retrieving local interfaces\n"); if(ooSocketCreateUDP(&sock)!= ASN_OK) @@ -686,7 +687,8 @@ int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList) memFreePtr(pctxt, pIf); continue; } - strcpy(addr, ast_inet_ntoa(((struct sockaddr_in*)&ifReq.ifr_addr)->sin_addr)); + memcpy(&sin, &ifReq.ifr_addr, sizeof(struct sockaddr_in)); + strcpy(addr, ast_inet_ntoa(sin.sin_addr)); OOTRACEDBGA2("\tIP address is %s\n", addr); pIf->addr = (char*)memAlloc(pctxt, strlen(addr)+1); if(!pIf->addr) @@ -709,7 +711,8 @@ int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList) memFreePtr(pctxt, pIf); continue; } - strcpy(mask, ast_inet_ntoa(((struct sockaddr_in *)&ifReq.ifr_netmask)->sin_addr)); + memcpy(&sin, &ifReq.ifr_netmask, sizeof(struct sockaddr_in)); + strcpy(mask, ast_inet_ntoa(sin.sin_addr)); OOTRACEDBGA2("\tMask is %s\n", mask); pIf->mask = (char*)memAlloc(pctxt, strlen(mask)+1); if(!pIf->mask) diff --git a/addons/ooh323c/src/ooh245.c b/addons/ooh323c/src/ooh245.c index 920df770fa3f5604c65a6875e012e233b976af89..9eee543162873349b51eebcd410e531ca380bcee 100644 --- a/addons/ooh323c/src/ooh245.c +++ b/addons/ooh323c/src/ooh245.c @@ -2409,6 +2409,132 @@ int ooOnReceivedRequestChannelClose(OOH323CallData *call, return ret; } +int ooSendRoundTripDelayRequest(OOH323CallData *call) +{ + int ret=0; + H245Message *ph245msg=NULL; + H245RequestMessage *request = NULL; + OOCTXT *pctxt=NULL; + H245RoundTripDelayRequest *rtdr; + ooTimerCallback *cbData=NULL; + + if (call->rtdrSend > call->rtdrRecv + call->rtdrCount) { + if(call->callState < OO_CALL_CLEAR) { + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_UNKNOWN; + call->q931cause = Q931RecoveryOnTimerExpiry; + } + return OO_FAILED; + } + + ret = ooCreateH245Message(call, &ph245msg, + T_H245MultimediaSystemControlMessage_request); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message " + "failed (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + + pctxt = call->msgctxt; + ph245msg->msgType = OORequestDelayRequest; + request = ph245msg->h245Msg.u.request; + request->t = T_H245RequestMessage_roundTripDelayRequest; + request->u.roundTripDelayRequest = (H245RoundTripDelayRequest *)ASN1MALLOC + (pctxt, sizeof(H245RoundTripDelayRequest)); + if(!request->u.roundTripDelayRequest) + { + OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayRequest " + "message (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + rtdr = request->u.roundTripDelayRequest; + memset(rtdr, 0, sizeof(H245RoundTripDelayRequest)); + rtdr->sequenceNumber = ++call->rtdrSend; + + OOTRACEDBGA3("Built RoundTripDelayRequest message (%s, %s)\n", + call->callType, call->callToken); + ret = ooSendH245Msg(call, ph245msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error:Failed to enqueue RoundTripDelayRequest to outbound queue. (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; + } else { + cbData = (ooTimerCallback*) memAlloc(call->pctxt, + sizeof(ooTimerCallback)); + if(!cbData) + { + OOTRACEERR3("Error:Unable to allocate memory for timer callback data." + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + cbData->call = call; + cbData->timerType = OO_RTD_TIMER; + if(!ooTimerCreate(call->pctxt, &call->timerList, &ooRTDTimerExpired, + call->rtdrInterval, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create RTDR timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + + } + + ooFreeH245Message(call, ph245msg); + + return ret; +} + +int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, + H245SequenceNumber sequenceNumber) +{ + int ret=0; + H245Message *ph245msg=NULL; + H245ResponseMessage *response = NULL; + OOCTXT *pctxt=NULL; + H245RoundTripDelayResponse *rtdr; + + ret = ooCreateH245Message(call, &ph245msg, + T_H245MultimediaSystemControlMessage_response); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message " + "failed (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + + pctxt = call->msgctxt; + ph245msg->msgType = OORequestDelayResponse; + response = ph245msg->h245Msg.u.response; + response->t = T_H245ResponseMessage_roundTripDelayResponse; + response->u.roundTripDelayResponse = (H245RoundTripDelayResponse *)ASN1MALLOC + (pctxt, sizeof(H245RoundTripDelayResponse)); + if(!response->u.roundTripDelayResponse) + { + OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayResponse " + "message (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + rtdr = response->u.roundTripDelayResponse; + memset(rtdr, 0, sizeof(H245RoundTripDelayResponse)); + rtdr->sequenceNumber = sequenceNumber; + + OOTRACEDBGA3("Built RoundTripDelayResponse message (%s, %s)\n", + call->callType, call->callToken); + ret = ooSendH245Msg(call, ph245msg); + if(ret != OO_OK) + { + OOTRACEERR3("Error:Failed to enqueue RoundTripDelayResponse to outbound queue. (%s, %s)\n", + call->callType, call->callToken); + } + + ooFreeH245Message(call, ph245msg); + + return ret; +} + /* We clear channel here. Ideally the remote endpoint should send CloseLogicalChannel and then the channel should be cleared. But there's no @@ -2609,6 +2735,11 @@ int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg) ooOnReceivedRequestChannelClose(call, request->u.requestChannelClose); break; + case T_H245RequestMessage_roundTripDelayRequest: + OOTRACEINFO4("Received roundTripDelayRequest - %d (%s, %s)\n", + request->u.roundTripDelayRequest->sequenceNumber, call->callType, call->callToken); + ooOnReceivedRoundTripDelayRequest(call, request->u.roundTripDelayRequest->sequenceNumber); + break; default: ; } /* End of Request Message */ @@ -2833,6 +2964,11 @@ int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg) ooOnReceivedRequestChannelCloseReject(call, response->u.requestChannelCloseReject); break; + case T_H245ResponseMessage_roundTripDelayResponse: + OOTRACEINFO4("Received roundTripDelayResponse - %d (%s, %s)\n", + response->u.roundTripDelayResponse->sequenceNumber, call->callType, call->callToken); + call->rtdrRecv = response->u.roundTripDelayResponse->sequenceNumber; + break; default: ; } @@ -3932,6 +4068,18 @@ int ooTCSTimerExpired(void *data) return OO_OK; } +int ooRTDTimerExpired(void *data) +{ + ooTimerCallback *cbData = (ooTimerCallback*)data; + OOH323CallData *call = cbData->call; + OOTRACEINFO3("Time to send new RTD request. (%s, %s)\n", + call->callType, call->callToken); + ASN1MEMFREEPTR(call->pctxt, cbData); + ooSendRoundTripDelayRequest(call); + return OO_OK; + +} + int ooOpenLogicalChannelTimerExpired(void *pdata) { ooTimerCallback *cbData = (ooTimerCallback*)pdata; diff --git a/addons/ooh323c/src/ooh245.h b/addons/ooh323c/src/ooh245.h index 353441bde58184d3b2f1f9ba146bc6ad23fe4c95..e8bce3fb9e6289fe92b508b7b6a56460a088e94f 100644 --- a/addons/ooh323c/src/ooh245.h +++ b/addons/ooh323c/src/ooh245.h @@ -631,6 +631,7 @@ int ooSessionTimerExpired(void *pdata); /** * @} */ +int ooRTDTimerExpired(void *pdata); int ooHandleRequestMode(OOH323CallData* call, H245RequestMode *requestMode); @@ -643,6 +644,12 @@ int ooSendRequestModeReject(OOH323CallData* call, void ooOnReceivedRequestModeAck(OOH323CallData* call, H245RequestModeAck * requestModeAck); +int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, + H245SequenceNumber sequenceNumber); + +int ooSendRoundTripDelayRequest(OOH323CallData *call); + + #ifdef __cplusplus } #endif diff --git a/addons/ooh323c/src/ooh323.c b/addons/ooh323c/src/ooh323.c index 02c925b84f028a2f6736325d040d0f236f1a8d5c..104e0bf0d088a2979758051c0c18c00336a3aeeb 100644 --- a/addons/ooh323c/src/ooh323.c +++ b/addons/ooh323c/src/ooh323.c @@ -1543,6 +1543,10 @@ int ooOnReceivedSignalConnect(OOH323CallData* call, Q931Message *q931Msg) } } + call->callState = OO_CALL_CONNECTED; + if (call->rtdrCount > 0 && call->rtdrInterval > 0) { + return ooSendRoundTripDelayRequest(call); + } return OO_OK; } @@ -2239,7 +2243,8 @@ int ooPopulateAliasList(OOCTXT *pctxt, OOAliases *pAliases, } switch(pAlias->type) { - case T_H225AliasAddress_dialedDigits: + /* Don't populate DialedDigits as alias they populate as prefixes + case T_H225AliasAddress_dialedDigits: pAliasEntry->t = T_H225AliasAddress_dialedDigits; pAliasEntry->u.dialedDigits = (ASN1IA5String)memAlloc(pctxt, strlen(pAlias->value)+1); @@ -2252,7 +2257,7 @@ int ooPopulateAliasList(OOCTXT *pctxt, OOAliases *pAliases, } strcpy(*(char**)&pAliasEntry->u.dialedDigits, pAlias->value); bValid = TRUE; - break; + break; */ case T_H225AliasAddress_h323_ID: pAliasEntry->t = T_H225AliasAddress_h323_ID; pAliasEntry->u.h323_ID.nchars = strlen(pAlias->value); diff --git a/addons/ooh323c/src/ooq931.c b/addons/ooh323c/src/ooq931.c index 06748b6d978cb0d721da04a92af43955be2c6c38..3f25885db8766c6224a1f6f5b1bfdea82a3747dd 100644 --- a/addons/ooh323c/src/ooq931.c +++ b/addons/ooh323c/src/ooq931.c @@ -2003,6 +2003,11 @@ int ooAcceptCall(OOH323CallData *call) /* memReset(&gH323ep.msgctxt); */ memReset(call->msgctxt); + call->callState = OO_CALL_CONNECTED; + + if (call->rtdrCount > 0 && call->rtdrInterval > 0) { + return ooSendRoundTripDelayRequest(call); + } return OO_OK; } @@ -3669,7 +3674,9 @@ const char* ooGetMsgTypeText (int msgType) "OOUserInputIndication", "OORequestModeAck", "OORequestModeReject", - "OORequestMode" + "OORequestMode", + "OORequestDelayResponse", + "OORequestDelayRequest" }; int idx = msgType - OO_MSGTYPE_MIN; return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText)); diff --git a/addons/ooh323c/src/ootypes.h b/addons/ooh323c/src/ootypes.h index 24bb6a2db9b588c2cb3bfdec6d6fc6daf8aa5635..83c20fa45d9ee9e1ce8d5eb61a8913d637ea1d81 100644 --- a/addons/ooh323c/src/ootypes.h +++ b/addons/ooh323c/src/ootypes.h @@ -188,8 +188,10 @@ typedef enum OOCallClearReason { #define OORequestModeAck 131 #define OORequestModeReject 132 #define OORequestMode 133 +#define OORequestDelayResponse 134 +#define OORequestDelayRequest 135 -#define OO_MSGTYPE_MAX 133 +#define OO_MSGTYPE_MAX 135 /* Timer types */ #define OO_CALLESTB_TIMER (1<<0) @@ -200,6 +202,7 @@ typedef enum OOCallClearReason { #define OO_RCC_TIMER (1<<5) #define OO_SESSION_TIMER (1<<6) #define OO_H245CONNECT_TIMER (1<<7) +#define OO_RTD_TIMER (1<<8) /** Maximum length for received messages */ #define MAXMSGLEN 4096 diff --git a/configs/chan_ooh323.conf.sample b/configs/chan_ooh323.conf.sample index 6d14bcbc51eeffae62bf5ae666a0300e22f84240..8dbdafc73a173e518dd1927aa2909ab51ac921a6 100644 --- a/configs/chan_ooh323.conf.sample +++ b/configs/chan_ooh323.conf.sample @@ -116,6 +116,11 @@ allow=ulaw ; h245alphanumeric, h245signal. ;Default - rfc 2833 dtmfmode=rfc2833 +; +; round trip delay request, default = 0,0 (not send) +; x - count of unreplied requests before hangup, y - interval in sec between requests +; +;roundtrip=x,y ; User/peer/friend definitions: ; User config options Peer config options