--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/untrustedcertificatedialog/tsrc/tlsconntest/tlsconnection.cpp Thu Jun 24 12:46:20 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 <e32debug.h>
+#include <SecureSocket.h>
+#include <ssl_internal.h> // 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();
+ }
+