From fa9d6969d6a7b19024bc62f62da28e599bf7a1ee Mon Sep 17 00:00:00 2001
From: Alexandr Anikin <may@telecom-service.ru>
Date: Sun, 14 Mar 2010 14:42:59 +0000
Subject: [PATCH] generate roundtrip delay requests and responses

added response to roundtrip delay requests from opposite side
added roundtrip delay request sending to opposite side after answer,
added options for sending request (interval between request and
count of unreplied requests before forced call hangup)

(closes issue #16976)
Reported by: vmikhelson
Patches:
      rtdr-1.6.0-2.patch uploaded by may213 (license 454)
Tested by: vmikhelson, may213



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@252277 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 addons/chan_ooh323.c            |  40 +++++++++
 addons/ooh323c/src/ooCalls.h    |   2 +
 addons/ooh323c/src/ooSocket.c   |   7 +-
 addons/ooh323c/src/ooh245.c     | 148 ++++++++++++++++++++++++++++++++
 addons/ooh323c/src/ooh245.h     |   7 ++
 addons/ooh323c/src/ooh323.c     |   9 +-
 addons/ooh323c/src/ooq931.c     |   9 +-
 addons/ooh323c/src/ootypes.h    |   5 +-
 configs/chan_ooh323.conf.sample |   5 ++
 9 files changed, 226 insertions(+), 6 deletions(-)

diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 7724c21d44..2ae95fae44 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 68dd3bfbd3..05494296ee 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 5905365507..7c1b000a43 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 920df770fa..9eee543162 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 353441bde5..e8bce3fb9e 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 02c925b84f..104e0bf0d0 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 06748b6d97..3f25885db8 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 24bb6a2db9..83c20fa45d 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 6d14bcbc51..8dbdafc73a 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
-- 
GitLab