networksecurity/tls/protocol/applicationdata.cpp
changeset 0 af10295192d8
child 67 bb2423252ea3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/tls/protocol/applicationdata.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,290 @@
+// Copyright (c) 2003-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:
+// SSL3.0 and TLS1.0 Application Data source file.
+// Describes the implementation of the Application data (transmission
+// and reception) state machines.
+// 
+//
+
+/**
+ @file
+*/
+
+#include "applicationdata.h"
+#include "tlsconnection.h"
+#include "recordprotocolevents.h"
+#include "AlertProtocolEvents.h"
+#include "hellorequest.h"
+
+
+CSendAppData* CSendAppData::NewL( CRecordComposer& aRecordComposer )
+{
+	LOG(Log::Printf(_L("CSendAppData::NewL()"));)
+	CSendAppData* self = new(ELeave) CSendAppData( aRecordComposer );
+  	LOG(Log::Printf(_L("self %x - %x"), self, (TUint)self + sizeof( CSendAppData ));)
+	CleanupStack::PushL( self );
+	self->ConstructL( aRecordComposer );
+	CleanupStack::Pop();
+	return self;
+}
+
+inline CSendAppData::CSendAppData( CRecordComposer& aRecordComposer ) :
+   iRecordComposer( aRecordComposer  )
+{
+	LOG(Log::Printf(_L("CSendAppData::CSendAppData()\n"));)
+	iHistory = KTlsApplicationData; // This shows explicitly where we are
+}
+
+CSendAppData::~CSendAppData()
+{
+	LOG(Log::Printf(_L("CSendAppData::~CSendAppData()\n"));)
+   SetSockXfrLength( NULL );
+   Cancel( KErrNone );
+	delete iSendAlert;
+}
+
+inline void CSendAppData::ConstructL( CRecordComposer& aRecordComposer )
+{
+	iSendAlert = new(ELeave)CSendAlert( *this, aRecordComposer );
+	LOG(Log::Printf(_L("CSendAppData::ConstructL() %x\n"), SendAlert());)
+	ResumeL();
+}
+
+void CSendAppData::Suspend()
+{
+	LOG(Log::Printf(_L("CSendAppData::Suspend()\n"));)
+   
+	iCurrentPos = iRecordComposer.CurrentPos();
+	iAppData = iRecordComposer.UserData();
+	iRecordComposer.SetUserData( NULL );
+}
+
+void CSendAppData::ResumeL()
+{
+	LOG(Log::Printf(_L("CSendAppData::ResumeL()\n"));)
+   
+	iRecordComposer.SetUserData( iAppData );
+	iRecordComposer.ReConstructL( this, iCurrentPos ); //it sets record type to ETlsAppDataContentType
+	iCurrentPos = 0;
+	
+	if ( !iActiveEvent )
+	{	//active event is the record composer
+		iActiveEvent = &iRecordComposer;
+	}
+}
+
+void CSendAppData::SetSockXfrLength( TInt* aLen )
+{
+	LOG(Log::Printf(_L("CSendAppData::SetSockXfrLength()\n"));)
+
+	iSockXfrLength = aLen;
+	if ( iSockXfrLength )
+	{
+		*iSockXfrLength = 0;
+	}
+}
+
+void CSendAppData::OnCompletion()
+{
+	LOG(Log::Printf(_L("CSendAppData::OnCompletion()\n"));)
+   
+	TDesC8* pAppData = iRecordComposer.UserData();
+	if ( pAppData ) //could have finished via an error
+	{
+		if ( iSockXfrLength )
+		{
+			*iSockXfrLength = iRecordComposer.CurrentPos();
+		}
+		if ( iLastError == KErrNone && iStatus.Int() == KErrNone )
+		{
+			//hello request received?
+			if ( iStateMachineNotify == iHelloReq && iHelloReq )
+			{//no user request completion, signal to hello request
+				iHelloReq->OnCompletion( this );
+				return;
+			}
+			// Anything more to send?
+			else if ( pAppData->Length() > iRecordComposer.CurrentPos() )
+			{	// No error (cancel) && still some app data in the app buffer =>
+				// => write another fragment
+				iActiveEvent = &iRecordComposer;
+				Start( iClientStatus, iStateMachineNotify );
+				return;
+			}
+		}
+	}
+   
+	iRecordComposer.SetUserData( NULL ); //we'r finished
+	iRecordComposer.ResetCurrentPos();
+
+	/* Fix for the TLS Client hang issue DEF130128.
+	 * In the case of where one of the state machines receives the 
+	 * asynchronous event alert due to TLS server reset, the state 
+	 * machine triggers the cleanup activities. The TlsConnection 
+	 * fails to clean up  the resources allocated for handling data 
+	 * transfer and TLS handshake in such cases if one of the state 
+	 * machines has issued the asynchronous server request and is 
+	 * waiting for the request to complete. The change made below 
+	 * will allow the code complete the pending status in such cases 
+	 * and allow the cleanup to proceed.
+	 */
+	if ( iStatus.Int() == KRequestPending )
+		{
+			TRequestStatus* p=&iStatus;
+			User::RequestComplete( p, iLastError );
+		}
+	/* End of fix for the TLS Client hang issue DEF130128. */
+	
+	CStateMachine::OnCompletion();
+}
+
+void CSendAppData::DoCancel()
+{
+	LOG(Log::Printf(_L("CSendAppData::DoCancel()\n"));)
+
+	iLastError = KErrCancel;
+	iRecordComposer.CancelAll();
+	CStateMachine::DoCancel();
+}
+
+//
+//
+CRecvAppData* CRecvAppData::NewL( CTlsConnection& aTlsConnection )
+{
+	LOG(Log::Printf(_L("CRecvAppData::NewL()"));)
+	CRecvAppData* self = new(ELeave) CRecvAppData( aTlsConnection );
+  	LOG(Log::Printf(_L("self %x - %x"), self, (TUint)self + sizeof( CRecvAppData ));)
+	CleanupStack::PushL( self );
+	self->ConstructL( aTlsConnection );
+	CleanupStack::Pop();
+	return self;
+}
+
+inline CRecvAppData::CRecvAppData( CTlsConnection& aTlsConnection ) :
+   iHeldData( 0, 0 ),
+   iRecordParser( aTlsConnection.RecordParser() )
+{
+	LOG(Log::Printf(_L("CRecvAppData::CRecvAppData()\n"));)
+	iHistory = KTlsApplicationData; // This shows explicitly where we are
+}
+
+CRecvAppData::~CRecvAppData()
+{
+	LOG(Log::Printf(_L("CRecvAppData::~CRecvAppData()\n"));)
+   SetSockXfrLength( NULL );
+   Cancel( KErrNone );
+	delete iSendAlert;
+}
+
+inline void CRecvAppData::ConstructL( CTlsConnection& aTlsConnection )
+{
+	iSendAlert = new(ELeave)CSendAlert( *this, aTlsConnection.RecordComposer() );
+	LOG(Log::Printf(_L("CRecvAppData::ConstructL() %x\n"), SendAlert());)
+	ResumeL( aTlsConnection );
+}
+
+void CRecvAppData::Suspend()
+{
+	LOG(Log::Printf(_L("CRecvAppData::Suspend()\n"));)
+   
+	iHeldData = iRecordParser.HeldData();
+	iAppData = iRecordParser.UserData();
+	iRecordParser.SetUserData( NULL );
+	iRecordParser.SetUserMaxLength( 0 );
+}
+
+void CRecvAppData::ResumeL( CTlsConnection& aTlsConnection )
+{
+	LOG(Log::Printf(_L("CRecvAppData::ResumeL()"));)
+	
+	__ASSERT_DEBUG( (iAppData && iClientStatus) || (!iAppData && !iClientStatus), TlsPanic(ETlsPanicAppDataResumeButNotStarted));
+	__ASSERT_DEBUG( iSendAlert, TlsPanic(ETlsPanicAlertReceived));
+	iRecordParser.SetUserData( iAppData );
+	iRecordParser.SetUserMaxLength( iAppData ? iAppData->MaxLength() : 0 );
+	iRecordParser.ReConstructL( this, iHeldData, *iSendAlert );
+
+	// Destroy the Rx list & add the only handshake event accepted during application data mode.
+	CHandshakeParser* pParser = iRecordParser.HandshakeParser();
+	pParser->DestroyRxList();
+	CHelloRequest* helloReq = new(ELeave)CHelloRequest( aTlsConnection, *this );
+	//coverity[leave_without_push]
+	LOG(Log::Printf(_L("helloReq %x - %x"), helloReq, (TUint)helloReq + sizeof( CHelloRequest ));)
+	pParser->AddToList( *helloReq );
+
+	aTlsConnection.SendAppData()->SetHelloRequest( helloReq ); //no ownership passed
+	if ( !iActiveEvent )
+	{	//active event is the record parser
+		iActiveEvent = &iRecordParser;
+	}
+}
+
+void CRecvAppData::OnCompletion()
+{
+	LOG(Log::Printf(_L("CRecvAppData::OnCompletion()\n"));)
+
+   if ( iLastError == KErrNone && iStatus.Int() == KErrNone )
+   {
+      if ( iRecordParser.TlsRecordType() == ETlsHandshakeContentType )
+      {//it could be just hello request received => suspend() could have already happened
+         return;
+      }
+	   TDes8* pAppData = iRecordParser.UserData();
+	   if ( pAppData ) //could have finished via an error
+	   {
+		   if ( iSockXfrLength && pAppData->Length() ) //are we to report RecvOneOrMore?
+		   {	//yes and finish
+			   *iSockXfrLength = pAppData->Length();
+		   }
+		   else if ( pAppData->Length() < pAppData->MaxLength() )
+		   {	//no error (cancel) && still some free room in the app data buffer =>
+			   //=> read another fragment
+			   iActiveEvent = &iRecordParser;
+			   Start( iClientStatus, iStateMachineNotify );
+			   return;
+		   }
+	   }
+   }
+   
+	iRecordParser.SetUserData( NULL ); //we'r finished
+	iRecordParser.SetUserMaxLength( 0 );
+	
+	/* Fix for the TLS Client hang issue DEF130128.
+	 * In the case of where one of the state machines receives the 
+	 * asynchronous event alert due to TLS server reset, the state 
+	 * machine triggers the cleanup activities. The TlsConnection 
+	 * fails to clean up  the resources allocated for handling data 
+	 * transfer and TLS handshake in such cases if one of the state 
+	 * machines has issued the asynchronous server request and is 
+	 * waiting for the request to complete. The change made below 
+	 * will allow the code complete the pending status in such cases 
+	 * and allow the cleanup to proceed.
+	 */
+	if ( iStatus.Int() == KRequestPending )
+		{
+			TRequestStatus* p=&iStatus;
+			User::RequestComplete( p, iLastError );
+		}
+	/* End of fix for the TLS Client hang issue DEF130128. */
+	
+	CStateMachine::OnCompletion();
+}
+
+void CRecvAppData::DoCancel()
+{
+	LOG(Log::Printf(_L("CRecvAppData::DoCancel()\n"));)
+   
+    iLastError = KErrCancel; 
+	iRecordParser.CancelAll();
+	CStateMachine::DoCancel();
+}