diff -r 000000000000 -r af10295192d8 networksecurity/tls/protocol/applicationdata.cpp --- /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(); +}