diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 4debfa269f88e6b1682076fd4e9a34018af934d9..2fac52ce55f31678ca9cc749a300a22753eb66ef 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -183,6 +183,7 @@ static struct ooh323_pvt {
 	int nat;
 	int amaflags;
 	int progsent;			/* progress is sent */
+	int alertsent;			/* alerting is sent */
 	struct ast_dsp *vad;
 	struct OOH323Regex *rtpmask;	/* rtp ip regexp */
 	char rtpmaskstr[120];
@@ -1236,13 +1237,15 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
 	    break;
       case AST_CONTROL_RINGING:
 	    if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING) {
-		if (gH323Debug) {
-			ast_debug(1, "Sending manual ringback for %s, res = %d\n",
-			callToken,
-			ooManualRingback(callToken));
-		} else {
-			ooManualRingback(callToken);
-		}
+		if (!p->alertsent) {
+			if (gH323Debug) {
+				ast_debug(1, "Sending manual ringback for %s, res = %d\n",
+					callToken,
+					ooManualRingback(callToken));
+			} else {
+				ooManualRingback(callToken);
+			}
+			p->alertsent = 1;
 	    }
 	 break;
 	case AST_CONTROL_SRCUPDATE:
diff --git a/addons/ooh323c/src/ooCalls.h b/addons/ooh323c/src/ooCalls.h
index 05494296ee2fe044959c3723312616c0bdd4cdf5..8f367769fe9874a81e1932ac922ff713baf0d01f 100644
--- a/addons/ooh323c/src/ooCalls.h
+++ b/addons/ooh323c/src/ooCalls.h
@@ -172,6 +172,7 @@ typedef struct OOH323CallData {
    OOCallState          callState;
    OOCallClearReason    callEndReason;
    int			q931cause;
+   ASN1UINT		h225version;
    unsigned             h245ConnectionAttempts;
    OOH245SessionState   h245SessionState;
    int                  dtmfmode;
diff --git a/addons/ooh323c/src/ooSocket.c b/addons/ooh323c/src/ooSocket.c
index f6547058e245b693a252fe1778c7b28a4ddb6a50..128049bdc44dd56c53a7e84ef4f7e5ef89c5ef53 100644
--- a/addons/ooh323c/src/ooSocket.c
+++ b/addons/ooh323c/src/ooSocket.c
@@ -191,7 +191,7 @@ typedef socklen_t OOSOCKLEN;
 int ooSocketCreate (OOSOCKET* psocket) 
 {
    int on;
-
+   int keepalive = 1, keepcnt = 24, keepidle = 120, keepintvl = 30;
    struct linger linger;
    OOSOCKET sock = socket (AF_INET,
                              SOCK_STREAM,
@@ -217,6 +217,11 @@ int ooSocketCreate (OOSOCKET* psocket)
       OOTRACEERR1("Error:Failed to set socket option linger\n");
       return ASN_E_INVSOCKET;
    }
+   setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&keepalive,
+			sizeof(keepalive));
+   setsockopt (sock, SOL_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
+   setsockopt (sock, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
+   setsockopt (sock, SOL_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
    *psocket = sock;
    return ASN_OK;
 }
diff --git a/addons/ooh323c/src/ooStackCmds.c b/addons/ooh323c/src/ooStackCmds.c
index 29878789e308ed2da4450fcb6d1df9151ae7b665..2cb1902be521e04bf00636e31d93e63565129d55 100644
--- a/addons/ooh323c/src/ooStackCmds.c
+++ b/addons/ooh323c/src/ooStackCmds.c
@@ -261,6 +261,9 @@ OOStkCmdStat ooManualProgress(const char *callToken)
          return OO_STKCMD_CONNECTIONERR;
    }
 
+   if (call->h225version < 4)
+      return OO_STKCMD_SUCCESS;
+
    memset(&cmd, 0, sizeof(OOStackCommand));
    cmd.type = OO_CMD_MANUALPROGRESS;
    cmd.param1 = (void*) malloc(strlen(callToken)+1);
diff --git a/addons/ooh323c/src/oochannels.c b/addons/ooh323c/src/oochannels.c
index 7fa85091441d20396388887eed2fc091b682ab6f..e16fdcc06572af1b5a67336fc7d1ff36d695fcc3 100644
--- a/addons/ooh323c/src/oochannels.c
+++ b/addons/ooh323c/src/oochannels.c
@@ -473,15 +473,6 @@ int ooAcceptH245Connection(OOH323CallData *call)
    OOTRACEINFO3("H.245 connection established (%s, %s)\n", 
                 call->callType, call->callToken);
 
-
-   /* 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;
-   }
    return OO_OK;
 }
 
@@ -1835,6 +1826,8 @@ int ooOnSendMsg
       }
       else{
          ooCloseH245Connection(call);
+	 if(call->callState < OO_CALL_CLEAR)
+	    call->callState = OO_CALL_CLEAR;
       }
       break;
    case OOCloseLogicalChannel:
diff --git a/addons/ooh323c/src/ooh245.c b/addons/ooh323c/src/ooh245.c
index d993c9ed2d71a3efa91b3672904eb43caa89ffdf..687e07eb53f71cccb7d0558458554f7194f177e5 100644
--- a/addons/ooh323c/src/ooh245.c
+++ b/addons/ooh323c/src/ooh245.c
@@ -2060,14 +2060,12 @@ int ooHandleH245Command(OOH323CallData *call,
                }
             }
             ooCloseH245Connection(call);
+	    if (call->callState < OO_CALL_CLEAR)
+	        call->callState = OO_CALL_CLEAR;
          }
          else{
 
             call->h245SessionState = OO_H245SESSION_ENDRECVD;
-#if 0
-            if(call->callState < OO_CALL_CLEAR)
-               call->callState = OO_CALL_CLEAR;
-#else 
             if(call->logicalChans)
             {
                OOTRACEINFO3("In response to received EndSessionCommand - "
@@ -2076,7 +2074,6 @@ int ooHandleH245Command(OOH323CallData *call,
                ooClearAllLogicalChannels(call);
             }
             ooSendEndSessionCommand(call);
-#endif
          }
             
             
diff --git a/addons/ooh323c/src/ooh323.c b/addons/ooh323c/src/ooh323.c
index 09df3c9c1472afc4afaea7f07595dd9522b464a4..33751067a0ba7b51846628b96de782e9ac4e7034 100644
--- a/addons/ooh323c/src/ooh323.c
+++ b/addons/ooh323c/src/ooh323.c
@@ -40,6 +40,7 @@ int ooOnReceivedCallProceeding(OOH323CallData *call, Q931Message *q931Msg);
 int ooOnReceivedAlerting(OOH323CallData *call, Q931Message *q931Msg);
 int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg);
 int ooHandleDisplayIE(OOH323CallData *call, Q931Message *q931Msg);
+int ooHandleH2250ID (OOH323CallData *call, H225ProtocolIdentifier protocolIdentifier);
 
 int ooHandleDisplayIE(OOH323CallData *call, Q931Message *q931Msg) {
    Q931InformationElement* pDisplayIE;
@@ -57,6 +58,17 @@ int ooHandleDisplayIE(OOH323CallData *call, Q931Message *q931Msg) {
    return OO_OK;
 }
 
+int ooHandleH2250ID (OOH323CallData *call, H225ProtocolIdentifier protocolIdentifier) {
+   if (!call->h225version && (protocolIdentifier.numids >= 6) &&
+	(protocolIdentifier.subid[3] == 2250)) {
+	call->h225version = protocolIdentifier.subid[5];
+	OOTRACEDBGC4("Extract H.225 remote version, it's %d, (%s, %s)\n", call->h225version, 
+						call->callType, call->callToken);
+
+   }
+   return OO_OK;
+}
+
 int ooHandleFastStart(OOH323CallData *call, H225Facility_UUIE *facility)
 {
    H245OpenLogicalChannel* olc;
@@ -241,7 +253,9 @@ int ooHandleFastStart(OOH323CallData *call, H225Facility_UUIE *facility)
        }
       }
    } else if (OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
-	ret =ooSendTCSandMSD(call);
+	if (call->h225version >= 4) {
+		ret =ooSendTCSandMSD(call);
+	}
 	if (ret != OO_OK)
 		return ret;
    }
@@ -372,6 +386,7 @@ int ooOnReceivedSetup(OOH323CallData *call, Q931Message *q931Msg)
                   "%s\n", call->callType, call->callToken);
       return OO_FAILED;
    }
+   ooHandleH2250ID(call, setup->protocolIdentifier);
    memcpy(call->callIdentifier.guid.data, setup->callIdentifier.guid.data, 
           setup->callIdentifier.guid.numocts);
    call->callIdentifier.guid.numocts = setup->callIdentifier.guid.numocts;
@@ -384,9 +399,9 @@ int ooOnReceivedSetup(OOH323CallData *call, Q931Message *q931Msg)
    pDisplayIE = ooQ931GetIE(q931Msg, Q931DisplayIE);
    if(pDisplayIE)
    {
-      call->remoteDisplayName = (char *) memAlloc(call->pctxt, 
+      call->remoteDisplayName = (char *) memAllocZ(call->pctxt, 
                                  pDisplayIE->length*sizeof(ASN1OCTET)+1);
-      strcpy(call->remoteDisplayName, (char *)pDisplayIE->data);
+      strncpy(call->remoteDisplayName, (char *)pDisplayIE->data, pDisplayIE->length*sizeof(ASN1OCTET));
    }
    /*Extract Remote Aliases, if present*/
    if(setup->m.sourceAddressPresent)
@@ -618,6 +633,7 @@ int ooOnReceivedCallProceeding(OOH323CallData *call, Q931Message *q931Msg)
       return OO_FAILED;
    }
 
+   ooHandleH2250ID(call, callProceeding->protocolIdentifier);
    /* Handle fast-start */
    if(OO_TESTFLAG (call->flags, OO_M_FASTSTART))
    {
@@ -846,6 +862,7 @@ int ooOnReceivedAlerting(OOH323CallData *call, Q931Message *q931Msg)
       }
       return OO_FAILED;
    }
+   ooHandleH2250ID(call, alerting->protocolIdentifier);
    /*Handle fast-start */
    if(OO_TESTFLAG (call->flags, OO_M_FASTSTART) &&
       !OO_TESTFLAG(call->flags, OO_M_FASTSTARTANSWERED))
@@ -996,7 +1013,9 @@ int ooOnReceivedAlerting(OOH323CallData *call, Q931Message *q931Msg)
       	OOTRACEINFO3("Tunneling and h245address provided."
                      "Giving preference to Tunneling (%s, %s)\n", 
                    	call->callType, call->callToken);
-	ret =ooSendTCSandMSD(call);
+	if (call->h225version >= 4) {
+		ret =ooSendTCSandMSD(call);
+	}
 	if (ret != OO_OK)
 		return ret;
 
@@ -1038,6 +1057,10 @@ int ooOnReceivedAlerting(OOH323CallData *call, Q931Message *q931Msg)
             call->callState = OO_CALL_CLEAR;
          }
          return OO_FAILED;
+       } else {
+	if (call->h225version >= 4) {
+		ret =ooSendTCSandMSD(call);
+	}
        }
       }
    }
@@ -1076,6 +1099,7 @@ int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg)
       }
       return OO_FAILED;
    }
+   ooHandleH2250ID(call, progress->protocolIdentifier);
    /*Handle fast-start */
    if(OO_TESTFLAG (call->flags, OO_M_FASTSTART) &&
       !OO_TESTFLAG(call->flags, OO_M_FASTSTARTANSWERED))
@@ -1227,7 +1251,9 @@ int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg)
       	OOTRACEINFO3("Tunneling and h245address provided."
                      "Giving preference to Tunneling (%s, %s)\n", 
                      call->callType, call->callToken);
-	ret =ooSendTCSandMSD(call);
+	if (call->h225version >= 4) {
+		ret =ooSendTCSandMSD(call);
+	}
 	if (ret != OO_OK)
 		return ret;
    } else if(progress->m.h245AddressPresent) {
@@ -1268,6 +1294,10 @@ int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg)
             call->callState = OO_CALL_CLEAR;
          }
          return OO_FAILED;
+       } else {
+	if (call->h225version >= 4) {
+		ret =ooSendTCSandMSD(call);
+	}
        }
       }
    }
@@ -1313,7 +1343,7 @@ int ooOnReceivedSignalConnect(OOH323CallData* call, Q931Message *q931Msg)
       }
       return OO_FAILED;
    }
-
+   ooHandleH2250ID(call, connect->protocolIdentifier);
    /*Handle fast-start */
    if(OO_TESTFLAG (call->flags, OO_M_FASTSTART) && 
       !OO_TESTFLAG (call->flags, OO_M_FASTSTARTANSWERED))
@@ -1548,24 +1578,24 @@ int ooOnReceivedSignalConnect(OOH323CallData* call, Q931Message *q931Msg)
       OOTRACEDBGB3("Finished tunneled messages in Connect. (%s, %s)\n",
                     call->callType, call->callToken);
 
-      /*
+   }
+   /*
         Send TCS as call established and no capability exchange has yet 
         started. This will be true only when separate h245 connection is not
         established and tunneling is being used.
-      */
-      if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
-      {
-         /*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;
-         }
-      }
-
+   */
+   if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
+   {
+        /*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;
+        }
    }
+
    call->callState = OO_CALL_CONNECTED;
    if (call->rtdrCount > 0 && call->rtdrInterval > 0) {
         return ooSendRoundTripDelayRequest(call);
@@ -1786,6 +1816,9 @@ int ooOnReceivedFacility(OOH323CallData *call, Q931Message * pQ931Msg)
    H225TransportAddress_ipAddress_ip *ip = NULL;
    OOTRACEDBGC3("Received Facility Message.(%s, %s)\n", call->callType, 
                                                         call->callToken);
+
+   ooHandleDisplayIE(call, pQ931Msg);
+
    /* Get Reference to H323_UU_PDU */
    if(!pQ931Msg->userInfo)
    {
@@ -1803,6 +1836,7 @@ int ooOnReceivedFacility(OOH323CallData *call, Q931Message * pQ931Msg)
    facility = pH323UUPdu->h323_message_body.u.facility;
    if(facility)
    {
+      ooHandleH2250ID(call, facility->protocolIdentifier);
       /* Depending on the reason of facility message handle the message */
       if(facility->reason.t == T_H225FacilityReason_transportedInformation)
       {
@@ -1980,6 +2014,7 @@ int ooHandleStartH245FacilityMessage
      OOTRACEINFO3("INFO: H.245 connection already established with remote"
                   " endpoint (%s, %s)\n", call->callType, call->callToken);
    }
+   ooSendTCSandMSD(call);
    return OO_OK;
 }
 
diff --git a/addons/ooh323c/src/ooq931.c b/addons/ooh323c/src/ooq931.c
index d0233f36313ea9a81872d2c40a4e1033dc24fe1b..dddcf15ec0145b3a07d5736d0ebf5baad1254148 100644
--- a/addons/ooh323c/src/ooq931.c
+++ b/addons/ooh323c/src/ooq931.c
@@ -53,6 +53,7 @@ EXTERN int ooQ931Decode
    int offset, x;
    int rv = ASN_OK;
    char number[128];
+   char *display = NULL;
    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
    OOCTXT *pctxt = call->msgctxt;
 
@@ -164,9 +165,15 @@ EXTERN int ooQ931Decode
       }
       if(ie->discriminator == Q931DisplayIE)
       {
-         OOTRACEDBGB1("   Display IE = {\n");
-         OOTRACEDBGB2("      %s\n", ie->data);
-         OOTRACEDBGB1("   }\n");
+	 if (!(display = memAllocZ(pctxt, ie->length + 1))) {
+		OOTRACEERR4("Can't alloc DisplayIE buffer for %n bytes, (%s, %s)\n", ie->length,
+				call->callType, call->callToken);
+	 } else {
+            memcpy(display, ie->data,ie->length);
+            OOTRACEDBGB1("   Display IE = {\n");
+            OOTRACEDBGB2("      %s\n", display);
+            OOTRACEDBGB1("   }\n");
+	 }
       }
 
       if(ie->discriminator == Q931KeypadIE)
@@ -1451,7 +1458,9 @@ int ooSendAlerting(OOH323CallData *call)
       OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
    }
 
-   ooSendTCSandMSD(call);
+   if (call->h225version >= 4) {
+	ooSendTCSandMSD(call);
+   }
    memReset (call->msgctxt);
 
    return ret;
@@ -1588,7 +1597,9 @@ int ooSendProgress(OOH323CallData *call)
    if (!OO_TESTFLAG(call->flags, OO_M_TUNNELING) && call->h245listener)
       ooSendStartH245Facility(call);
 
-   ooSendTCSandMSD(call);
+   if (call->h225version >= 4) {
+	ooSendTCSandMSD(call);
+   }
    memReset (call->msgctxt);
 
    return ret;
@@ -1957,12 +1968,16 @@ int ooAcceptCall(OOH323CallData *call)
    }
 
 
-   /* Add h245 listener address. Do not add H245 listener address in case
-      of fast-start. */
+   /* Add h245 listener address. */
+   /* Do not add H245 listener address in case
+      of fast-start. why? */
+   /* May 20110205 */
+   /* Send h245 listener addr any case if H245 connection isn't established */
    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)
+       ( (!call->h245listener && ooCreateH245Listener(call) == OO_OK) ||
+         !call->pH245Channel))
    {
       connect->m.h245AddressPresent = TRUE;
       connect->h245Address.t = T_H225TransportAddress_ipAddress;
@@ -1997,6 +2012,7 @@ int ooAcceptCall(OOH323CallData *call)
       return OO_FAILED;
    }
    /* memReset(&gH323ep.msgctxt); */
+   ooSendTCSandMSD(call);
    memReset(call->msgctxt);
 
    call->callState = OO_CALL_CONNECTED;
@@ -2721,11 +2737,8 @@ int ooH323MakeCall_helper(OOH323CallData *call)
 
    /* For H.323 version 4 and higher, if fast connect, tunneling should be 
       supported.
+      why?
    */
-   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);