diff -r 63339781d179 -r 09b1ac925e3f pkiutilities/untrustedcertificatedialog/tsrc/tlsconntest/tlsconnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkiutilities/untrustedcertificatedialog/tsrc/tlsconntest/tlsconnection.cpp Tue Aug 31 16:04:40 2010 +0300 @@ -0,0 +1,471 @@ +/* +* Copyright (c) 2010 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: Secure connections test application +* +*/ + +#include "tlsconnection.h" +#include +#include +#include // KSolInetSSL, KSoSSLDomainName + +_LIT( KData, "GET index.html" ); +_LIT( KSecureProtocol, "TLS1.0" ); +_LIT( KCommDBIapId, "IAP\\Id" ); +_LIT8( KNewLine, "\n" ); + +const TInt KRecvBufferLength = 0x4000; +const TInt KOneSecondInMicroseconds = 1000000; + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------- +// CTlsConnection::NewL +// --------------------------------------------------------- +// +CTlsConnection* CTlsConnection::NewL( MTlsConnectionObserver& aObs ) + { + RDebug::Print( _L("CTlsConnection::NewL()") ); + CTlsConnection* self = new ( ELeave ) CTlsConnection( aObs ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::~CTlsConnection() +// ----------------------------------------------------------------------------- +// +CTlsConnection::~CTlsConnection() + { + RDebug::Print( _L("CTlsConnection::~CTlsConnection()") ); + Cancel(); + iDelayTimer.Close(); + CloseSession(); + delete iSendBuffer; + delete iSendBufPtr; + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::ConnectL() +// ----------------------------------------------------------------------------- +// +void CTlsConnection::ConnectL( const TDesC& aHostName, TInt aPort, TInt aDelay ) + { + RDebug::Print( _L("CTlsConnection::Connect() host '%S', port %d, delay %d"), + &aHostName, aPort, aDelay ); + CloseConnection(); + + // Parameters + if( iHostName ) + { + delete iHostName; + iHostName = NULL; + } + iHostName = aHostName.AllocL(); + iPort = aPort; + iDelay = aDelay; + + // Save host name in 8-bit form for server certificate checking + if( iHostNameForCertCheck ) + { + delete iHostNameForCertCheck; + iHostNameForCertCheck = NULL; + } + iHostNameForCertCheck = HBufC8::NewL( aHostName.Length() ); + TPtr8 ptr( iHostNameForCertCheck->Des() ); + ptr.Copy( aHostName ); + + // Convert send data to 8-bit and add newline at the end + if( iSendBuffer || iSendBufPtr ) + { + delete iSendBuffer; + iSendBuffer = NULL; + delete iSendBufPtr; + iSendBufPtr = NULL; + } + iSendBuffer = HBufC8::NewL( KData().Length() + 1 ); + iSendBufPtr = new( ELeave ) TPtr8( iSendBuffer->Des() ); + iSendBufPtr->Copy( KData ); + iSendBufPtr->Append( KNewLine ); + + // Connect + RDebug::Printf( "CTlsConnection::ConnectL iConnection.Open" ); + User::LeaveIfError( iConnection.Open( iSockServer ) ); + RDebug::Printf( "CTlsConnection::ConnectL iConnPref.SetDirection" ); + iConnPref.SetDirection( ECommDbConnectionDirectionOutgoing ); + if( iCurrentIap ) + { + // uses the same IAP as before + RDebug::Printf( "CTlsConnection::ConnectL SetIapId(%d)", iCurrentIap ); + iConnPref.SetIapId( iCurrentIap ); + iConnPref.SetDialogPreference( ECommDbDialogPrefDoNotPrompt ); + } + else + { + // not defined, prompts the IAP from user + RDebug::Printf( "CTlsConnection::ConnectL ECommDbDialogPrefPrompt" ); + iConnPref.SetDialogPreference( ECommDbDialogPrefPrompt ); + } + StateChange( EConnectingNetwork ); + RDebug::Printf( "CTlsConnection::ConnectL iConnection.Start" ); + iConnection.Start( iConnPref, iStatus ); + SetActive(); + RDebug::Printf( "CTlsConnection::ConnectL end" ); + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::Disconnect() +// ----------------------------------------------------------------------------- +// +void CTlsConnection::Disconnect() + { + Cancel(); + CloseConnection(); + StateChange( EDisconnected ); + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::RunL +// ----------------------------------------------------------------------------- +// +void CTlsConnection::RunL() + { + if( iState == EReading && ( iStatus.Int() == KErrEof || iStatus.Int() == KErrSSLAlertCloseNotify ) ) + { + RDebug::Printf( "CTlsConnection::RunL: EReading, EOF: iStatus = %d", iStatus.Int() ); + StateChange( EAllDone ); + } + else if( iStatus.Int() == KErrNone ) + { + switch ( iState ) + { + case EConnectingNetwork: + RDebug::Printf( "CTlsConnection::RunL: EConnectingNetwork" ); + if( !iCurrentIap ) + { + iConnection.GetIntSetting( KCommDBIapId, iCurrentIap ); + } + if( iDelay ) + { + TTimeIntervalMicroSeconds32 delay( iDelay * KOneSecondInMicroseconds ); + iDelayTimer.After( iStatus, delay ); + StateChange( EOpeningDelay ); + } + else + { + iConnection.ProgressNotification( iProgress, iStatus ); + StateChange( EResolvingHostName ); + } + SetActive(); + break; + + case EOpeningDelay: + iConnection.ProgressNotification( iProgress, iStatus ); + StateChange( EResolvingHostName ); + SetActive(); + break; + + case EResolvingHostName: + { + RDebug::Printf( "CTlsConnection::RunL: EResolvingHostName" ); + TInt err = iHostResolver.Open( iSockServer, KAfInet, KProtocolInetUdp, iConnection ); + User::LeaveIfError( err ); + iHostResolver.GetByName( *iHostName, iNameEntry, iStatus ); + StateChange( EConnectingServer ); + SetActive(); + } + break; + + case EConnectingServer: + { + iRemoteAddr.SetFamily( KAfInet ); + iRemoteAddr = TInetAddr( iNameEntry().iAddr ); + iRemoteAddr.SetPort( iPort ); + + RDebug::Printf( "CTlsConnection::RunL: EConnectingServer" ); + TInt err = iSocket.Open( iSockServer, KAfInet, KSockStream, KProtocolInetTcp, iConnection ); + RDebug::Printf( "CTlsConnection::RunL: iSocket.Open ret %d", err ); + User::LeaveIfError( err ); + iSocket.Connect( iRemoteAddr, iStatus ); + StateChange( EHandshaking ); + SetActive(); + } + break; + + case EHandshaking: + { + RDebug::Printf( "CTlsConnection::RunL: EHandshaking" ); + if( iSecureSocket ) + { + delete iSecureSocket; + iSecureSocket = NULL; + } + iSecureSocket = CSecureSocket::NewL( iSocket, KSecureProtocol ); + iSecureSocket->SetDialogMode( EDialogModeAttended ); + // Server name must be set, otherwise CCTSecurityDialogsAO fails with KErrArgument + iSecureSocket->SetOpt( KSoSSLDomainName, KSolInetSSL, *iHostNameForCertCheck ); + iSecureSocket->StartClientHandshake( iStatus ); + StateChange( EConnecting ); + SetActive(); + } + break; + + case EConnecting: + { + RDebug::Printf( "CTlsConnection::RunL: EConnecting" ); + // Check if connection is closed + const TInt stage( iProgress().iStage ); + if( stage == KConnectionClosed || stage == KLinkLayerClosed ) + { + StateChange( EDisconnected ); + } + else + { + iConnection.ProgressNotification( iProgress, iStatus ); + StateChange( ESending ); + SetActive(); + } + } + break; + + case ESending: + RDebug::Printf( "CTlsConnection::RunL: ESending" ); + iSecureSocket->Send( *iSendBufPtr, iStatus, iSendLength ); + StateChange( EReading ); + SetActive(); + break; + + case EReading: + iTotalRecvCount += iRecvLength(); + RDebug::Printf( "CTlsConnection::RunL: EReading, read %d bytes", iTotalRecvCount ); + iObserver.HandleTransferData( iRecvBuffer->Des(), iTotalRecvCount ); + + iRecvBufPtr->Zero(); + iSecureSocket->RecvOneOrMore( *iRecvBufPtr, iStatus, iRecvLength ); + SetActive(); + break; + + default: + break; + } + } + else + { + RDebug::Printf( "CTlsConnection::RunL: ERROR iStatus %d", iStatus.Int() ); + CloseConnection(); + StateChange( EDisconnected, iStatus.Int() ); + } + } + +// --------------------------------------------------------------------------- +// CTlsConnection::DoCancel() +// --------------------------------------------------------------------------- +// +void CTlsConnection::DoCancel() + { + RDebug::Printf( "CTlsConnection::DoCancel(), iState=%d", iState ); + + switch( iState ) + { + case EConnectingNetwork: + iConnection.Stop(); + break; + + case EOpeningDelay: + iDelayTimer.Cancel(); + iConnection.Stop(); + break; + + case EResolvingHostName: + iConnection.CancelProgressNotification(); + iConnection.Stop(); + break; + + case EConnectingServer: + iHostResolver.Cancel(); + iConnection.Stop(); + break; + + case EHandshaking: + iSocket.CancelConnect(); + iConnection.Stop(); + break; + + case EConnecting: + if( iSecureSocket ) + { + iSecureSocket->CancelHandshake(); + delete iSecureSocket; + iSecureSocket = NULL; + } + iSocket.Close(); + iConnection.Stop(); + break; + + case ESending: + if( iSecureSocket ) + { + iSecureSocket->CancelSend(); + delete iSecureSocket; + iSecureSocket = NULL; + } + iSocket.Close(); + iConnection.Stop(); + break; + + case EReading: + if( iSecureSocket ) + { + iSecureSocket->CancelRecv(); + delete iSecureSocket; + iSecureSocket = NULL; + } + iSocket.Close(); + iConnection.Stop(); + break; + + case EAllDone: + case EIdle: + case EDisconnected: + default: + break; + } + + StateChange( EDisconnected ); + } + + +// ----------------------------------------------------------------------------- +// CTlsConnection::RunError() +// ----------------------------------------------------------------------------- +// +TInt CTlsConnection::RunError( TInt aError ) + { + RDebug::Printf( "CTlsConnection::RunError, aError: %d", aError ); + CloseConnection(); + StateChange( EDisconnected, aError ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::CTlsConnection() +// ----------------------------------------------------------------------------- +// +CTlsConnection::CTlsConnection( MTlsConnectionObserver& aObs ) : + CActive( CActive::EPriorityStandard ), iObserver( aObs ), iState( ENotInitialized ) + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::ConstructL() +// ----------------------------------------------------------------------------- +// +void CTlsConnection::ConstructL() + { + RDebug::Printf( "CTlsConnection::ConstructL begin" ); + + User::LeaveIfError( iDelayTimer.CreateLocal() ); + RDebug::Printf( "CTlsConnection::ConstructL iSockServer" ); + User::LeaveIfError( iSockServer.Connect() ); + RDebug::Printf( "CTlsConnection::ConstructL iConnection" ); + User::LeaveIfError( iConnection.Open( iSockServer ) ); + RDebug::Printf( "CTlsConnection::ConstructL buffers" ); + iRecvBuffer = HBufC8::NewL( KRecvBufferLength ); + iRecvBufPtr = new( ELeave ) TPtr8( iRecvBuffer->Des() ); + StateChange( EIdle ); + + RDebug::Printf( "CTlsConnection::ConstructL end" ); + } + +// --------------------------------------------------------------------------- +// CTlsConnection::CloseConnection() +// --------------------------------------------------------------------------- +// +void CTlsConnection::CloseConnection() + { + RDebug::Printf( "CTlsConnection::CloseConnection begin" ); + if( iSecureSocket ) + { + delete iSecureSocket; + iSecureSocket = NULL; + } + iSocket.Close(); + iHostResolver.Close(); + if( iConnection.SubSessionHandle() ) + { + if( iState >= EConnectingNetwork ) + { + TInt err = iConnection.Stop(); + if( err != KErrNone ) + { + RDebug::Printf( "iConnection.Stop() failed: %d", err ); + } + } + iConnection.Close(); + } + RDebug::Printf( "CTlsConnection::CloseConnection end" ); + } + +// --------------------------------------------------------------------------- +// CTlsConnection::CloseSession() +// --------------------------------------------------------------------------- +// +void CTlsConnection::CloseSession() + { + RDebug::Printf( "CTlsConnection::CloseSession" ); + CloseConnection(); + iSockServer.Close(); + delete iHostName; + iHostName = NULL; + delete iHostNameForCertCheck; + iHostNameForCertCheck = NULL; + delete iRecvBuffer; + iRecvBuffer = NULL; + delete iRecvBufPtr; + iRecvBufPtr = NULL; + StateChange( EDisconnected ); + } + +// ----------------------------------------------------------------------------- +// CTlsConnection::StateChange() +// ----------------------------------------------------------------------------- +// +void CTlsConnection::StateChange( TTlsConnectionState aNewState, TInt aError ) + { + RDebug::Printf( "CTlsConnection::StateChange, aNewState=%d, aError=%d", aNewState, aError ); + if( aNewState != iState && iState != EAllDone ) + { + iState = aNewState; + iObserver.HandleNetworkEvent( aNewState, aError ); + } + } + +// --------------------------------------------------------------------------- +// CTlsConnection::ReadL() +// --------------------------------------------------------------------------- +// +void CTlsConnection::ReadL() + { + RDebug::Printf( "CTlsConnection::ReadL(), iState=%d", iState ); + + TPtr8 recvBuffer = iRecvBuffer->Des(); + recvBuffer.Zero(); + iSecureSocket->RecvOneOrMore( recvBuffer, iStatus, iRecvLength ); + SetActive(); + } +