multimediacommsengine/mmcesrv/mmceserver/src/mcereliablesender.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcereliablesender.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,345 @@
+/*
+* Copyright (c) 2005 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:  
+*
+*/
+
+
+
+
+#include <e32base.h>
+#include <e32cmn.h>
+#include <siprackheader.h>
+#include <sipconnection.h>
+#include <sipresponseelements.h>
+#include <siprequestelements.h>
+#include <sipcseqheader.h> 
+#include <siprseqheader.h> 
+#include <centralrepository.h>
+#include <sipsdkcrkeys.h>
+#include <stringpool.h>
+#include "mcesip.h"
+#include "mcesrvlogs.h"
+#include "mcereliableobserver.h"
+#include "mcereliablesender.h"
+#include "mceeventstatebase.h"
+
+// CONSTANTS
+const TInt KMaxTransTimeOut = 64;
+const TUint KTransInterval = 2;
+
+
+// -----------------------------------------------------------------------------
+// CMCEReliableSender::NewL ;
+// Two-phased constructor. ;
+// -----------------------------------------------------------------------------
+//
+CMceReliableSender* CMceReliableSender::NewL( MMceReliableObserver& aObserver )
+    {
+	CMceReliableSender* self = new( ELeave ) CMceReliableSender( aObserver );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::CMceReliableSender
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CMceReliableSender::CMceReliableSender( MMceReliableObserver& aObserver )
+: iObserver( &aObserver )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CMceReliableSender::~CMceReliableSender()
+    {
+	delete iDTimer;
+	delete iResponseElements;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::ConstructL
+// Symbian 2nd phase constructor.
+// -----------------------------------------------------------------------------
+//
+void CMceReliableSender::ConstructL()
+    {
+	const TUint	KMaxRSec = 0x7fffffff;
+    const TUint	KMinRSec = 1;
+	TInt timerT1;
+	CRepository* repository = CRepository::NewLC( KCRUidSIP );
+	User::LeaveIfError( repository->Get( KSIPTransactionTimerT1, timerT1 ));
+	CleanupStack::PopAndDestroy( repository );
+    
+    iT1 = timerT1;
+     
+    iRetransTimer = 1;
+    iTotaltime = 0;
+    
+    iSequenceNumber = MceSip::Random( KMinRSec, KMaxRSec );
+	iTransactionMatched = EFalse;
+	iTransactionStatus = EFalse;	// No Pending transaction Yet 
+	iTransTimeoutFlag = EFalse;
+	
+    // Create the timer entry 
+	iDTimer = CDeltaTimer::NewL( CActive::EPriorityStandard );
+		
+	TCallBack cb( TimerExpire, this );
+	iDeltaEntry.Set( cb );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::Rseq
+// -----------------------------------------------------------------------------
+//
+TUint CMceReliableSender::Rseq( CSIPServerTransaction& aTransaction )
+    {
+    TInt tInProcess = 0;
+	if  ( iTransactionStatus )
+	    {
+	    MCESRV_DEBUG( "CMceReliableSender::Rseq: Transsaction in Process");
+	    return tInProcess;
+	    }
+   	else if( &aTransaction == iServerTransaction )
+	    {
+		iSequenceNumber = iSequenceNumber + 1;
+		return iSequenceNumber;
+	    }
+	else
+	    {
+	    return iSequenceNumber;
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::SendResponseL
+// -----------------------------------------------------------------------------
+//
+void CMceReliableSender::SendResponseL( CSIPServerTransaction& aTransaction, 
+                                        CSIPResponseElements* aElements )
+    {
+	if  ( iTransactionStatus )
+	    {
+        User::Leave( KErrInUse );
+	    }
+
+    iServerTransaction = &aTransaction;
+	CSIPResponseElements* xResponses;
+
+	// Set the Transaction in progree Flag  
+	
+	iTransactionStatus = ETrue;
+    TUint queueTimer = 0;
+         	
+	xResponses = ResponseCloneL( *aElements );
+	CleanupStack::PushL( xResponses );
+    iServerTransaction->SendResponseL( xResponses );
+    MCESRV_DEBUG_DVALUE( 
+        "CMceReliableSender::SendResponseL - timer value:", iRetransTimer );
+    CleanupStack::Pop( xResponses );
+   	iResponseElements = aElements;  
+   	
+   	queueTimer = iRetransTimer * iT1 *KConversionMilliToMicro;
+	iDTimer->Queue( queueTimer, iDeltaEntry );
+    iRetransTimer = iRetransTimer * KTransInterval;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::ResponseCloneL
+// -----------------------------------------------------------------------------
+//
+CSIPResponseElements* CMceReliableSender::ResponseCloneL( 
+                                            CSIPResponseElements& aElements )
+    {
+	CSIPResponseElements* cElements = 
+	    CSIPResponseElements::NewLC( aElements.StatusCode(), 
+	                                 aElements.ReasonPhrase() );
+	// Creating messge Elements
+	CSIPMessageElements& msgElements = aElements.MessageElements();
+	CSIPMessageElements& cloneMsgElements = cElements->MessageElements();
+
+
+	// Copying Contents 
+	if  ( msgElements.Content().Length() )
+	    {
+    	const CSIPContentTypeHeader* contentType = msgElements.ContentType();
+		CSIPContentTypeHeader* cloneContentType = 
+		    static_cast<CSIPContentTypeHeader *>( contentType->CloneL() );
+		CleanupStack::PushL( cloneContentType );
+
+		HBufC8* contentBuffer = HBufC8::NewLC( msgElements.Content().Length() );
+		TPtr8 contentsPtr = contentBuffer->Des();
+		contentsPtr.Append( msgElements.Content() );
+    
+		cloneMsgElements.SetContentL( contentBuffer, cloneContentType );
+		CleanupStack::Pop( contentBuffer );
+		CleanupStack::Pop( cloneContentType );
+    	}
+
+  	// User Headers
+	const RPointerArray<CSIPHeaderBase>& headers = msgElements.UserHeaders();
+	if  ( headers.Count() )
+	    {
+		RPointerArray<CSIPHeaderBase> tmpHeaders;
+		CSIPHeaderBase::PushLC( &tmpHeaders );
+		for(TInt i = 0; i < headers.Count(); i++)
+		    {
+			CSIPHeaderBase* userHeader = headers[i]->CloneL();
+			CleanupStack::PushL( userHeader );
+			tmpHeaders.AppendL( userHeader );
+			
+			CleanupStack::Pop( userHeader );
+		    }
+
+		cloneMsgElements.SetUserHeadersL( tmpHeaders );
+		CleanupStack::Pop( &tmpHeaders );
+	    }
+    CleanupStack::Pop( cElements );
+	return cElements;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::PrackReceived
+// -----------------------------------------------------------------------------
+//
+TBool CMceReliableSender::PrackReceived( CSIPServerTransaction& aPrack )
+    {
+	TBool transactionMatched = EFalse;
+	RStringF rackHeaderStr = SIPStrings::StringF( SipStrConsts::ERAckHeader );
+	RStringF rseqStr = SIPStrings::StringF( SipStrConsts::ERSeqHeader );
+			
+	const CSIPRequestElements* reqElements = aPrack.RequestElements();
+	CSIPHeaderBase*	headerBase = 
+	    MceSip::FindHeader( reqElements->MessageElements(), rackHeaderStr );
+	const CSIPRAckHeader* rackHeader = static_cast<CSIPRAckHeader *>( headerBase );
+	
+	const CSIPRequestElements* sReqElements = iServerTransaction->RequestElements();    
+    const CSIPCSeqHeader* cseqHeader = sReqElements->CSeqHeader();
+    
+    CSIPHeaderBase* headerBase3 =  
+        MceSip::FindHeader( iResponseElements->MessageElements(), rseqStr );
+    const CSIPRSeqHeader* rseqHeader = static_cast<CSIPRSeqHeader *> ( headerBase3 );
+  
+      
+   	if  ( ( rackHeader && cseqHeader && rseqHeader ) && 
+   	    ( rackHeader->CSeqNum() == cseqHeader->Seq() ) &&
+	    ( rackHeader->Method() == sReqElements->Method() ) && 
+	    ( rackHeader->Seq() == rseqHeader->Value()) )
+
+	    {
+	    MCESRV_DEBUG( "CMceReliableSender::PrackReceived: prack matched");
+	    transactionMatched = ETrue;
+        }
+    
+    if  ( transactionMatched )
+	    {
+        // Cease the Re-Transmission of Reliable Response 
+                
+        iDTimer->Remove( iDeltaEntry ); 
+        iTransactionMatched = ETrue;
+        iTransactionStatus = EFalse;    
+   
+      	return ETrue;
+  	    }
+
+    MCESRV_DEBUG( "CMceReliableSender::PrackReceived: no prack matched");
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::TimerExpire
+// -----------------------------------------------------------------------------
+//
+TInt CMceReliableSender::TimerExpire( TAny *aSelf )
+    { 
+    TInt error;
+    TUint queueTimer;
+    TUint tmpTotalTime;
+               
+    CMceReliableSender* me = static_cast<CMceReliableSender *>( aSelf );
+            
+    if ( !me->iTransTimeoutFlag )        
+        {
+        TRAP(error, me->CloneAndSendResponseL());
+  
+        if ( error )
+            {
+            me->iObserver->ReliableFailed( *me->iServerTransaction, error );
+            }
+        }
+        
+    else 
+        {
+        me->TimeOut( me->iServerTransaction );    
+        }
+		
+	if ( me->iRetransTimer <= KMaxTransTimeOut && me->iTransactionStatus )
+		{
+	    tmpTotalTime = me->iTotaltime;
+		me->iTotaltime = me->iTotaltime + me->iRetransTimer; // acumlated time
+			
+		if ( me->iTotaltime <= KMaxTransTimeOut )
+		    {
+		    queueTimer = me->iRetransTimer * me->iT1 * KConversionMilliToMicro;
+		    }
+        else 
+           {
+            me->iTotaltime = tmpTotalTime;
+            queueTimer = ( KMaxTransTimeOut - me->iTotaltime ) * me->iT1 * KConversionMilliToMicro;
+            me->iTransTimeoutFlag = ETrue;
+            }
+            
+        me->iDTimer->Queue( queueTimer, me->iDeltaEntry );
+        me->iRetransTimer = me->iRetransTimer * KTransInterval;
+        MCESRV_DEBUG_DVALUE( 
+		"CMceReliableSender::TimerExpire: timer added", me->iRetransTimer );
+          
+		}
+
+	return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::CloneAndSendResponseL 
+// -----------------------------------------------------------------------------
+//
+void CMceReliableSender::CloneAndSendResponseL()
+    {
+    CSIPResponseElements* oResponses;
+    oResponses = ResponseCloneL( *iResponseElements );
+    MCESRV_DEBUG( 
+        "CMceReliableSender::CloneAndSendResponseL: responseElements cloned");
+    CleanupStack::PushL( oResponses );
+    iServerTransaction->SendResponseL( oResponses );
+    MCESRV_DEBUG( 
+        "CMceReliableSender::CloneAndSendResponseL: reliableResponse sent");
+    CleanupStack::Pop( oResponses );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceReliableSender::TimeOut
+// -----------------------------------------------------------------------------
+//
+void CMceReliableSender::TimeOut( CSIPServerTransaction* aTransaction )
+    {  
+	iObserver->NoPrackReceived( *aTransaction ); 
+	}
+
+// End of File