realtimenetprots/sipfw/SIP/Transaction/src/ClientTransaction.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Transaction/src/ClientTransaction.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,322 @@
+// 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          : ClientTransaction.cpp
+// Part of       : Transaction
+// Version       : SIP/5.0
+//
+
+
+
+#include "uri8.h"
+#include "SipAssert.h"
+#include "siperr.h"
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "sipfromheader.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "DeleteMgr.h"
+#include "UserAgentBase.h"
+#include "SIPMessageUtility.h"
+#include "MTransactionStore.h"
+
+#include "Transmitter.h"
+#include "ClientTransaction.h"
+
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::CClientTransaction
+// -----------------------------------------------------------------------------
+//
+CClientTransaction::CClientTransaction(CUserAgentBase& aUserAgent,
+									   CTransmitter& aTransmitter,
+									   MTimerManager& aTimers,
+									   CTransactionState& aInitialState,
+									   TTimerValues& aTimerValues,
+									   MTransactionStore& aTransactionStore) :
+	CTransaction(aUserAgent,
+				 aTransmitter,
+				 aTimers,
+				 aInitialState,
+				 aTimerValues),
+	iTransactionStore(aTransactionStore)
+	{	
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::~CClientTransaction
+// -----------------------------------------------------------------------------
+//
+CClientTransaction::~CClientTransaction()
+	{
+	delete iOutboundProxy;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::TransactionId
+// If transaction is detached from UAC, transaction knows the TransactionId.
+// -----------------------------------------------------------------------------
+//
+TTransactionId CClientTransaction::TransactionId() const
+	{
+	__TEST_INVARIANT;
+
+	if (iUserAgent)
+		{
+		return iUserAgent->TransactionId();
+		}
+
+	return iTransactionId;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::StoreRequest
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::StoreRequest(CSIPRequest& aReq,
+									  const TInetAddr& aAddress,
+									  const TSIPTransportParams& aParams,
+									  RStringF aTransportProtocol,
+									  TBool aForceUDP,
+									  CUri8* aOutboundProxy)
+	{
+	__TEST_INVARIANT;
+	__ASSERT_ALWAYS(!iOutgoingMsg && !iOutboundProxy,
+					User::Panic(_L("ClientTa:StoreRq"), KErrAlreadyExists));
+
+	iOutgoingMsg = &aReq;
+	iRemoteAddr = aAddress;
+	iTransportParams = aParams;
+	iTransportProtocol = aTransportProtocol;
+	iForceUDP = aForceUDP;
+	iOutboundProxy = aOutboundProxy;
+
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::ClearProxy
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::ClearProxy()
+	{
+	__TEST_INVARIANT;
+
+	iOutboundProxy = NULL;
+	
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::SendToTransmitterL
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::SendToTransmitterL()
+	{
+	__TEST_INVARIANT;
+	__SIP_ASSERT_LEAVE(iOutgoingMsg && iTransmitter, KErrNotFound);    
+
+	iTransmitter->SendRequestL(static_cast<CSIPRequest&>(*iOutgoingMsg),							   
+							   iRemoteAddr,
+							   iForceUDP,
+							   iTransportParams,
+							   iOutboundProxy,
+							   this);
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::ShouldTaHandleResponse
+// Drop invalid response, but don't terminate transaction just because a broken
+// SIP response came from the network.
+//
+// A Non-INVITE transaction passes each response to upper layer only once and
+// filters out retransmissions.
+//
+// INVITE transaction passes every 1xx to upper layer, as INVITE may've forked.
+// -----------------------------------------------------------------------------
+//
+TBool CClientTransaction::ShouldTaHandleResponse(CSIPResponse* aResp) const
+	{
+	__TEST_INVARIANT;
+	__ASSERT_DEBUG(aResp,
+		User::Panic(_L("ClientTa:ShouldTaHandleResp !aResp"), KErrArgument));
+
+    //After a final response, ShouldTaHandleResponse must not be used
+	__ASSERT_DEBUG(iReceivedResponseCode < 200,
+	   User::Panic(_L("ClientTa:ShouldTaHandleResp iRecvRespCode>=200"),
+       KErrSIPInvalidTransactionState));
+
+	if ( !CheckReceivedResponse(*aResp) ||
+		 (!IsInviteTransaction() &&
+	      (iReceivedResponseCode == aResp->ResponseCode())) )
+	    {
+	    delete aResp;
+	    return EFalse;
+	    }
+
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::PassResponseToUserAgentL
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::PassResponseToUserAgentL(CSIPResponse* aResp)
+	{
+	__TEST_INVARIANT;
+    __SIP_ASSERT_LEAVE(iUserAgent, KErrNotFound);
+    __SIP_ASSERT_LEAVE(aResp, KErrArgument);
+
+	TUint respCode = aResp->ResponseCode();
+	iUserAgent->ReceiveL(aResp);
+	iReceivedResponseCode = respCode;
+
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::CheckReceivedResponse
+// From-tag must match the request's tag. Response must have exactly one Via.
+// -----------------------------------------------------------------------------
+//
+TBool CClientTransaction::CheckReceivedResponse(CSIPResponse& aResp) const
+	{
+	__TEST_INVARIANT;
+
+	RStringF from = SIPStrings::StringF(SipStrConsts::EFromHeader);	
+	if (!aResp.HasHeader(from))
+		{
+		return EFalse;
+		}
+
+	__ASSERT_DEBUG(iOutgoingMsg,
+		User::Panic(_L("ClientTa:ChkRecvResp !iOutMsg"), KErrNotFound));
+
+	TSglQueIter<CSIPHeaderBase> iterReq = iOutgoingMsg->Headers(from);
+	TSglQueIter<CSIPHeaderBase> iterResp = aResp.Headers(from);
+
+    return CSIPMessageUtility::CompareTags(
+		static_cast<CSIPFromHeader&>(*iterReq),
+		static_cast<CSIPFromHeader&>(*iterResp)) &&
+		(aResp.HeaderCount(SIPStrings::StringF(SipStrConsts::EViaHeader)) == 1);
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::RunIndependently
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::RunIndependently(TTransactionId aTransactionId,
+										  CDeleteMgr* aDeleteMgr,
+										  TBool aClearTransmitter)
+	{
+	__TEST_INVARIANT;
+	__ASSERT_DEBUG(!iDeleteMgr,
+		User::Panic(_L("ClientTa:RunIndependently iDM!=0"), KErrAlreadyExists));
+    __SIP_ASSERT_RETURN(aDeleteMgr, KErrArgument);
+
+	iTransactionId = aTransactionId;
+	iDeleteMgr = aDeleteMgr;
+
+	if (aClearTransmitter)
+		{
+		iTransmitter->DetachCallback(this);
+		iTransmitter = NULL;
+		}
+
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::CheckForTransportChange
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::CheckForTransportChange()
+	{
+	__TEST_INVARIANT;
+	__SIP_ASSERT_RETURN(iOutgoingMsg, KErrNotFound);
+
+	UpdateTransportProtocol(*iOutgoingMsg);
+
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::IcmpErrorL
+// Terminate with KErrSIPICMPFailure if transaction sends using UDP to the failed address
+// KErrSIPICMPFailure will be passed to observers like Profile Agent
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::IcmpErrorL(const TInetAddr& aAddress,
+								    CSipConnectionMgr::TICMPError /*aError*/)
+	{
+	__TEST_INVARIANT;
+
+	if (IsUnreliableTransportUsed() &&
+		CSIPMessageUtility::CompareTInetAddr(iRemoteAddr,
+											 TransportProtocol(),
+											 aAddress))
+		{
+        TerminatedL(KErrSIPICMPFailure);
+		}
+
+	__TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::TerminatedL
+// -----------------------------------------------------------------------------
+//
+void CClientTransaction::TerminatedL(TInt aReason)
+	{
+	__TEST_INVARIANT;
+	__SIP_INT_LOG1( "CClientTransaction::TerminatedL Error",
+					aReason )
+	if (!iTerminated)
+		{		
+		CTransaction::TerminatedL(aReason);
+
+		if (iDeleteMgr)
+			{
+			//Transaction is detached from UAC, and must remove itself from
+			//TransactionStore and use DeleteMgr to free itself.
+
+			if (iDeleteMgr->AddDeleteRequest(this) == KErrNone)
+				{
+				iTransactionStore.Remove(iTransactionId);
+				}
+			else
+				{
+				//Mark transaction to be deleted later on by MTransactionStore
+				iTransactionStore.UpdateTransactionId(iTransactionId,
+													  KEmptyTransactionId);
+				}
+			}
+		}
+
+	__TEST_INVARIANT;
+	}	
+
+// -----------------------------------------------------------------------------
+// CClientTransaction::__DbgTestInvariant
+// -----------------------------------------------------------------------------
+//
+
+void CClientTransaction::__DbgTestInvariant() const
+	{
+	if (iOutgoingMsg && !iOutgoingMsg->IsRequest())
+		{
+		User::Invariant();
+		}
+	}