realtimenetprots/sipfw/SIP/Transaction/src/InviteServerTaStates.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Transaction/src/InviteServerTaStates.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,482 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name          : InviteServerTaStates.cpp
+// Part of       : Transaction
+// Version       : SIP/5.0
+//
+
+
+
+#include "siperr.h"
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "SipAssert.h"
+#include "SIPMessageUtility.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+
+#include "InviteServerTa.h"
+#include "InviteServerTaStates.h"
+#include "ResponseQueueItem.h"
+
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::CInviteServerTa_Proceeding
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Proceeding::CInviteServerTa_Proceeding()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::~CInviteServerTa_Proceeding
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Proceeding::~CInviteServerTa_Proceeding()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::GetState
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Proceeding::GetState(CSIPInternalStates::TState& aState) const
+    {
+    aState = CSIPInternalStates::ETransactionProceeding;
+    }
+
+#if defined(USE_SIP_LOGS)
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::Log
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CInviteServerTa_Proceeding::Log() const
+	{
+	_LIT8(KState, "Proceeding");
+	return KState;
+	}
+#endif
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::SetNeighbourStates
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Proceeding::SetNeighbourStates(CTransactionState& aCompleted,
+											   CTransactionState& aSending2xx)
+	{
+	iCompleted = &aCompleted;
+	iSending2xx = &aSending2xx;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::ReceiveL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Proceeding::ReceiveL(CTransaction& aTransaction,
+                                          CSIPRequest* aRequest) const
+	{
+    __SIP_ASSERT_LEAVE(aRequest, KErrArgument);	
+
+	CInviteServerTransaction& ta = CInviteServerTransaction::Ptr(aTransaction);
+	if (!ta.RequestPassedToUA())
+		{
+		__ASSERT_ALWAYS(ta.UpdateTransportProtocol(*aRequest),
+					    User::Leave(KErrSIPMalformedMessage));
+		ta.Create100L(*aRequest);
+		}
+
+	//Send the most recent response, unless already being sent
+	if (!ta.IsTransmitterSending())
+		{
+		ta.SendToTransmitterL();
+		}
+
+	if (ta.RequestPassedToUA())
+		{
+		//Absorb retransmissions
+        delete aRequest;
+		}
+	else
+		{
+		//Pass the first INVITE to UAS
+		ta.PassRequestToUserAgentL(aRequest);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::SendResponseL
+// Queue the new response, if a previous response is being sent.
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Proceeding::SendResponseL(CTransaction& aTransaction,
+								  CSIPResponse* aResp,
+								  RStringF aProtocol,
+								  const TSIPTransportParams& aParams) const
+	{
+    __SIP_ASSERT_LEAVE(aResp, KErrArgument);
+    __SIP_ASSERT_LEAVE(CSIPMessageUtility::CheckTransport(aProtocol),
+                       KErrArgument);
+
+	CInviteServerTransaction& ta = CInviteServerTransaction::Ptr(aTransaction);
+	TUint respCode = aResp->ResponseCode();
+	CResponseQueueItem* respItem =
+		CResponseQueueItem::NewLC(aResp, aParams, ETrue);
+
+	if (ta.IsTransmitterSending())
+		{
+		ta.AddResponseToSendQueueL(respItem);
+		}
+	else
+		{
+		/* TimerH is started after the StateChange and sending the Response
+		 * This is done to avoid the timer expiry in proceeding state if 
+		 * SendAndStoreResponseL() function leaves and state change doesn't happen
+		 * In proceeding State, timer expiry is not expected and not handled 
+		 */
+		ta.ResponseSent(respCode, *iSending2xx, *iCompleted);
+		
+		ta.SendAndStoreResponseL(respItem, aProtocol);
+		
+		if (respCode >= 300)
+		    {
+		    ta.StartTimerHL();
+		    }
+		}
+	CleanupStack::Pop(respItem);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::SendCompleteL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Proceeding::SendCompleteL(CTransaction& aTransaction) const
+	{
+	CInviteServerTransaction& ta = CInviteServerTransaction::Ptr(aTransaction);
+	CResponseQueueItem* respItem = ta.GetResponseFromSendQueue();
+			
+     /* TimerH is started after the StateChange and sending the Response
+      * This is done to avoid the timer expiry in proceeding state if 
+      * SendAndStoreResponseL() function leaves and state change doesn't happen
+      * In proceeding State, timer expiry is not expected and not handled 
+      */
+	if (respItem)
+		{
+		CleanupStack::PushL(respItem);
+
+		TUint respCode = respItem->Response().ResponseCode();
+		
+		ta.ResponseSent(respCode, *iSending2xx, *iCompleted);
+		        
+		ta.SendAndStoreResponseL(respItem);
+		        
+		if (respCode >= 300)
+		    {
+            ta.StartTimerHL();
+		    }
+		CleanupStack::Pop(respItem);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Proceeding::SendFailedL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Proceeding::SendFailedL(CTransaction& aTransaction,
+											 TInt aError) const
+	{
+	aTransaction.TerminatedL(aError);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::CInviteServerTa_Completed
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Completed::CInviteServerTa_Completed()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::~CInviteServerTa_Completed
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Completed::~CInviteServerTa_Completed()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::GetState
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Completed::GetState(CSIPInternalStates::TState& aState) const
+    {
+    aState = CSIPInternalStates::ETransactionCompleted;
+    }
+
+#if defined(USE_SIP_LOGS)
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::Log
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CInviteServerTa_Completed::Log() const
+	{
+	_LIT8(KState, "Completed");
+	return KState;
+	}
+#endif
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::SetNeighbourStates
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Completed::SetNeighbourStates(CTransactionState& aConfirmed)
+	{
+	iConfirmed = &aConfirmed;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::SendCompleteL
+// Only one timer G exists at once. It can already exist if:
+// 1. Timer G is started
+// 2. INVITE is received and response sent
+// 3. SendCompleteL event comes while timer G is running
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Completed::SendCompleteL(CTransaction& aTransaction) const
+	{
+	if (aTransaction.IsUnreliableTransportUsed())
+		{
+		CInviteServerTransaction::Ptr(aTransaction).StartTimerGUnlessExistsL();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::SendFailedL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Completed::SendFailedL(CTransaction& aTransaction,
+											TInt aError) const
+	{
+	aTransaction.TerminatedL(aError);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::ReceiveL
+// Don't pass ACK to UAS. If retransmitted INVITE, retransmit the most recent
+// response unless already being sent.
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Completed::ReceiveL(CTransaction& aTransaction,
+                                         CSIPRequest* aRequest) const
+	{
+    __SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+
+	CInviteServerTransaction& ta = CInviteServerTransaction::Ptr(aTransaction);
+
+	if (CSIPMessageUtility::IsAck(*aRequest))
+		{
+		ta.EnterConfirmedStateL(*iConfirmed);
+		}
+	else 
+        {
+        if ((aRequest->Method() == SIPStrings::StringF(SipStrConsts::EInvite))
+            &&
+            !ta.IsTransmitterSending())
+		    {
+		    ta.SendToTransmitterL();
+            }
+		}
+
+    delete aRequest;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Completed::TimerExpiredL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Completed::TimerExpiredL(CTransaction& aTransaction,
+											  TTimerId aTimerId,
+											  TAny* aTimerParam) const
+	{    
+    __SIP_ASSERT_LEAVE(aTimerParam, KErrArgument);
+	
+	HandleTimerExpirationL(aTransaction, aTimerId, aTimerParam);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::CInviteServerTa_Confirmed
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Confirmed::CInviteServerTa_Confirmed()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::~CInviteServerTa_Confirmed
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Confirmed::~CInviteServerTa_Confirmed()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::GetState
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Confirmed::GetState(CSIPInternalStates::TState& aState) const
+    {
+    aState = CSIPInternalStates::ETransactionConfirmed;
+    }
+
+#if defined(USE_SIP_LOGS)
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::Log
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CInviteServerTa_Confirmed::Log() const
+	{
+	_LIT8(KState, "Confirmed");
+	return KState;
+	}
+#endif
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::CanContinueWithoutOutgoingMsg
+// This is never called for a server side.
+// -----------------------------------------------------------------------------
+//
+TBool CInviteServerTa_Confirmed::CanContinueWithoutOutgoingMsg() const
+	{
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::SendCompleteL
+// Happens if entered Confirmed state before CTransmitter finished sending.
+// Nothing is sent anymore, so no need to update transport protocol.
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Confirmed::SendCompleteL(CTransaction& /*aTransaction*/) const
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::SendFailedL
+// No action, wait for timer I to expire.
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Confirmed::SendFailedL(CTransaction& /*aTransaction*/,
+											TInt /*aError*/) const
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::ReceiveL
+// Absorb any additional ACKs.
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Confirmed::ReceiveL(CTransaction& /*aTransaction*/,
+                                         CSIPRequest* aRequest) const
+	{
+    __SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+
+    delete aRequest;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Confirmed::TimerExpiredL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Confirmed::TimerExpiredL(CTransaction& aTransaction,
+											  TTimerId aTimerId,
+											  TAny* aTimerParam) const
+	{    
+    __SIP_ASSERT_LEAVE(aTimerParam, KErrArgument);	
+
+	HandleTimerExpirationL(aTransaction, aTimerId, aTimerParam);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::CInviteServerTa_Sending2xx
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Sending2xx::CInviteServerTa_Sending2xx()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::~CInviteServerTa_Sending2xx
+// -----------------------------------------------------------------------------
+//
+CInviteServerTa_Sending2xx::~CInviteServerTa_Sending2xx()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::GetState
+// 2xx was sent but SendCompleteL not yet received. Treat state as terminated,
+// as "Sending2xx" is implementation's internal state.
+// -----------------------------------------------------------------------------
+//
+void
+CInviteServerTa_Sending2xx::GetState(CSIPInternalStates::TState& aState) const
+    {
+    aState = CSIPInternalStates::ETransactionTerminated;
+    }
+
+#if defined(USE_SIP_LOGS)
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::Log
+// Don't log transition to this state, as RFC doesn't specify it.
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CInviteServerTa_Sending2xx::Log() const
+	{
+    return EnteringThisStateIsntLogged();
+	}
+#endif
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::CanContinueWithoutOutgoingMsg
+// This is never called for a server side.
+// -----------------------------------------------------------------------------
+//
+TBool CInviteServerTa_Sending2xx::CanContinueWithoutOutgoingMsg() const
+	{
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::SendCompleteL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Sending2xx::SendCompleteL(CTransaction& aTransaction) const
+	{    
+	aTransaction.TerminatedL(KErrNone);
+	}
+
+// -----------------------------------------------------------------------------
+// CInviteServerTa_Sending2xx::SendFailedL
+// -----------------------------------------------------------------------------
+//
+void CInviteServerTa_Sending2xx::SendFailedL(CTransaction& aTransaction,
+											 TInt aError) const
+	{
+	aTransaction.TerminatedL(aError);
+	}