networksecurity/tlsprovider/Test/tlstest2/handshakestep.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/tlsprovider/Test/tlstest2/handshakestep.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,713 @@
+// Copyright (c) 2006-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:
+//
+
+/**
+ @file handshakestep.cpp
+ @internalTechnology
+*/
+#include "handshakestep.h"
+
+#include <tlsprovinterface.h>
+
+
+_LIT(KWebAddress,"WebAddress");
+_LIT(KWebPage,"WebPage");
+_LIT(KPortNum,"PortNum");
+_LIT(KExpectedFinalCipher, "ExpectedFinalCipherSuit");
+_LIT(KExpectedSetCipherError, "ExpectedSetCipherError");
+_LIT(KExpectedHandshakeError, "ExpectedHandshakeError");
+_LIT8(KSimpleGet, "GET /");
+_LIT8(KGetTail, " HTTP/1.0\r\n\r\n");
+_LIT8(KExpectedPageContent, "Hello world");
+_LIT8(KPSK_IDENTITY, "Client_identity");
+_LIT8(KPSK_KEY, "0123456789"); 
+_LIT(KNumServerNames, "NumServerNames");
+_LIT(KServerNameBase, "ServerName");
+
+
+
+// CertRequest tester active.
+CHandShakeTesterActive::CHandShakeTesterActive( CTestExecuteLogger& aLogger ) : 
+   CActive( EPriorityStandard ),
+   iLogger( aLogger )
+	{
+	CActiveScheduler::Add( this );
+	}
+	
+CHandShakeTesterActive::~CHandShakeTesterActive()
+	{
+   
+	}
+
+/** This is the core of the test, it handshakes a TLS test server, if succesfull it
+    requests a web page from the TLS server, if the page was received succesfully it
+    checks its content. Finally it checks the cipher suite used is what was expected. 
+	@param None
+	@return TVeredic EPass if all test sequence was completed an succesful.
+	*/
+TVerdict CHandShakeTesterActive::DoSecureConnectionTestL(CHandShakeStep* master)
+	{
+	TInt error_Returned;
+	
+	iStepPointer = master;
+	// Negociates secure connection.
+	error_Returned = HandShakeL();
+	if (error_Returned != iStepPointer->iExpectedHandshakeError)
+		{
+		ERR_PRINTF3(_L("Handshake failed, Expected error: %D Received Error: %D"), iStepPointer->iExpectedHandshakeError, error_Returned);
+		return EFail;
+		} 
+	else if( error_Returned != KErrNone) 
+		{
+		// An error was received but it was expected, communication can not continue as handshake failed.
+		ERR_PRINTF2(_L("Test abbreviated as expected handshake error %D was received."), error_Returned);
+		return EPass;  // Terminates test.	
+		}
+		
+	// request a web page to server.
+	if (MakePageRequest() != KErrNone)
+		{
+		ERR_PRINTF1(_L("Page request failed"));
+		return EFail;
+		} 
+
+	// Invokes appropiate methods to receive web page.
+	GetPageReceivedL();
+		
+	//	Verify that the page received has the expected content.
+ 	if (VerifyPageReceived() != KErrNone)
+		{
+		ERR_PRINTF1(_L("Page received not what expected"));
+		return EFail;
+		}   
+		
+	// debug, outputs page received to file.
+	// OutputPageToFileL(iStepPointer->iRcvPage); // debug 	
+		
+	// 	Check that the cipher suite negociated on handshake is the one
+	//  expected by the tester.
+	if (VerifyFinalCipherUsed() != KErrNone)
+		{
+		ERR_PRINTF1(_L("The final cipher Suite used not what expected"));
+		return EFail;
+		}   
+	return EPass; 
+	}
+
+void CHandShakeStep::GetPskL(const HBufC8 */*aPskIdentityHint*/, HBufC8 *&aPskIdentity, HBufC8 *&aPskKey)
+	{   
+    
+	aPskIdentity = KPSK_IDENTITY().AllocL();
+	aPskKey = KPSK_KEY().AllocL();
+
+	return;
+	}
+
+/** Establishes secure connection to TLS test server by using 
+    CSecureSocket::StartClientHandshake method.
+	@param None
+	@return TInt ,return error code returned by status of StartClientHandshake method.
+	*/
+TInt CHandShakeTesterActive::HandShakeL()
+	{
+	_LIT(KTLS1,"TLS1.0");
+	iStepPointer->iTlsSocket = CSecureSocket::NewL( iStepPointer->iSocket, KTLS1 );
+
+	// Clears any previous options
+	iStepPointer->iTlsSocket->FlushSessionCache();
+
+	// Sets Call back if needed.
+	iStepPointer->SetPskL();
+	
+	// Sets Null cipher if needed.
+	iStepPointer->SetNullCipherL();
+
+	// No client authentication or dialogs for this test.
+	iStepPointer->iTlsSocket->SetClientCertMode(EClientCertModeIgnore);
+	iStepPointer->iTlsSocket->SetDialogMode(EDialogModeUnattended);
+	
+	// Sets Server Name
+	if(iStepPointer->iUseServerNames)
+		{
+		TPckgC<CDesC8Array *> serverNamePkg(iStepPointer->iServerNamesArray);
+		User::LeaveIfError(iStepPointer->iTlsSocket->SetOpt(KSoServerNameIndication, KSolInetSSL, serverNamePkg));	
+		}
+
+	// Alternatively dialog mode attended could be used for manual tests.
+	// 	iStepPointer->iTlsSocket->SetClientCertMode(EClientCertModeOptional); // debug
+	// 	iStepPointer->iTlsSocket->SetDialogMode(EDialogModeAttended); // debug
+
+	// Set cipher suits to be presented in client hello message for handshake.
+	TInt setCipherSuitesError;
+	setCipherSuitesError = iStepPointer->iTlsSocket->SetAvailableCipherSuites( *(iStepPointer->iBufCipherSuitesFromIni));   
+
+	if ( setCipherSuitesError != iStepPointer->iExpectedSetSuitesError)
+		{
+		ERR_PRINTF3(_L("The SetAvailableCipherSuites method returned error: %d but error expected was: %d"), setCipherSuitesError , iStepPointer->iExpectedSetSuitesError);
+		User::Leave(KErrGeneral);	
+		}
+	// start the handshake 
+	iStepPointer->iTlsSocket->StartClientHandshake( iStatus);  
+	iState = ESecureConnected; 
+	SetActive();
+	CActiveScheduler::Start(); 
+
+	return iStatus.Int();  
+	}	
+
+/** Requests web page to TLS test server. 
+	@param None
+	@return TInt ,return error code returned by status of CSecureSocket::Send method.
+	*/
+TInt  CHandShakeTesterActive::MakePageRequest()
+	{
+	// Create a GET request
+	iStepPointer->iSndBuffer += KSimpleGet;
+	iStepPointer->iSndBuffer += iStepPointer->iConnectSettings.iPage;
+	iStepPointer->iSndBuffer += KGetTail;
+
+	// Send the request
+	iStepPointer->iTlsSocket->Send( iStepPointer->iSndBuffer, iStatus, iStepPointer->iBytesSent );
+	iState = EGetRequestSent;
+	SetActive();
+	CActiveScheduler::Start();
+	return iStatus.Int();  
+	}
+
+/** Receives web page previously requested to TLS test server. 
+	@param None
+	@return TInt ,return error code returned by status of CSecureSocket::Recv method.
+	*/
+void CHandShakeTesterActive::GetPageReceivedL()
+	{
+	// check for unexpected error.
+	if(iStatus != KErrEof && iStatus != KErrNone)
+		{
+		ERR_PRINTF2(_L("Unexpected error received on get page requested: %d"), iStatus.Int());
+		User::Leave(iStatus.Int());		
+		}
+	
+	// First receive invoked (status equals to KErrNone)
+	if(iStatus == KErrNone) 
+		{
+		iStepPointer->iRcvBuffer.SetLength( 0 );
+		iStepPointer->iTlsSocket->Recv( iStepPointer->iRcvBuffer, iStatus );
+		iState = EGetPageReceived;
+		SetActive();
+		CActiveScheduler::Start();
+		INFO_PRINTF1(_L("New packet received (for page request)"));
+		// Append received packet to page received so far. 
+		iStepPointer->iRcvPage.Append(iStepPointer->iRcvBuffer);	
+		}
+	
+	// KErrEof or buffer with length zero  received.
+	if(iStatus == KErrEof || iStepPointer->iRcvBuffer.Length() == 0)
+		{
+		// Tells the state machine to stop requesting for more packets.
+		iState = EIdle;
+		return;
+		}
+
+	}
+
+/** Compares the received page content against expected content.
+    At present the expected content is hardcoded in constant KExpectedPageContent,
+    if more sofisticated web pages checkings are needed test code may need to be modified to
+    read expected content from binary file.  
+	@param None
+	@return KErrNone if webpage is what is expected , otherwise returns KErrGeneral.
+	*/	
+TInt CHandShakeTesterActive::VerifyPageReceived()
+	{
+	if( iStepPointer->iRcvPage == KExpectedPageContent)
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return KErrGeneral;
+		}
+	}
+
+/** Checks that the cipher suit agreed in the TLS handshake is what the tester
+	was expecting.
+   	@param None
+	@return KErrNone if final cipher suite is what is expected , otherwise returns KErrGeneral.
+	*/
+TInt CHandShakeTesterActive::VerifyFinalCipherUsed()
+	{
+	TBuf8<2>	finalCipherBuffer; 
+	TInt    	finalCipher=0;
+	iStepPointer->iTlsSocket->CurrentCipherSuite(finalCipherBuffer);
+	// Converts two bytes buffer in single integer.
+	finalCipher += finalCipherBuffer[1];
+	finalCipher += (finalCipherBuffer[0] << 8);
+
+	if( iStepPointer->iExpectedFinalCipher == finalCipher)
+		{
+		return KErrNone;
+		}
+	else   
+		{
+		ERR_PRINTF3(_L("Used cipher: %d. Expected cipher: %d"), finalCipher, iStepPointer->iExpectedFinalCipher );
+		return KErrGeneral;
+		}
+	}
+	
+void CHandShakeTesterActive::OutputPageToFileL(const TDesC8& aPageReceived)
+	{
+	RFs	fs;
+	User::LeaveIfError (fs.Connect());
+	TDriveUnit sysDrive (RFs::GetSystemDrive());
+	TBuf<128> rName (sysDrive.Name());;
+	rName.Append(_L("\\tlstest2\\myresults\\"));
+			
+	TInt err = fs.MkDir(rName);
+	if (err != KErrNone && err != KErrAlreadyExists)
+		{
+		// This line will panic if directory does not exist.
+		User::Leave(err);	
+		}
+				
+	RFile file;
+	CleanupClosePushL(file);
+	
+	_LIT(KExtension, ".html");
+	rName.Append(iStepPointer->ConfigSection());
+	rName.Append(KExtension);
+	rName.LowerCase();
+	User::LeaveIfError(file.Replace(fs, rName, EFileWrite | EFileStream));
+	User::LeaveIfError(file.Write(aPageReceived));
+	CleanupStack::PopAndDestroy(&file);
+	fs.Close ();
+	}
+
+TInt CHandShakeTesterActive::RunError(TInt aError)
+	{
+	iRunError = aError;
+	CActiveScheduler::Stop();
+	return KErrNone;
+	}
+
+
+
+/** RunL method used for all asyncronous requests made by test code.
+   	*/
+void CHandShakeTesterActive::RunL()
+	{
+		iRunError =KErrNone;
+	
+		User::LeaveIfError(iStatus.Int());
+	
+		switch(iState)
+			{
+			case EIdle:
+				CActiveScheduler::Stop();
+				break;
+			
+			case ESecureConnected:
+				INFO_PRINTF1(_L(" secure connection made "));
+				iState = EIdle;
+				CActiveScheduler::Stop();
+				break;
+			case EGetRequestSent:
+				INFO_PRINTF1(_L(" Page requested "));
+				iState = EIdle;
+				CActiveScheduler::Stop();
+				break; 
+			case EGetPageReceived:
+				// Keeps getting packages until KErrEof is received.  
+				GetPageReceivedL();
+				// This line will be reach only after all packages received.
+				CActiveScheduler::Stop();
+				break; 
+			default:
+				{
+				INFO_PRINTF1(_L("HandShakeTesterActive: State corrupted."));
+				User::Leave(KErrCorrupt);
+				}
+			} 
+	return; 
+	}
+
+CHandShakeStep::CHandShakeStep()
+	{
+	SetTestStepName(KHandShakeTestStep);
+	}
+
+CHandShakeStep::~CHandShakeStep()
+	{
+	delete iBufCipherSuitesFromIni;
+	iSndBuffer.Close();
+	iRcvBuffer.Close();	
+	iRcvPage.Close();
+	if (iActiveObjTest)
+		{
+		delete iActiveObjTest;
+		}
+	}
+
+/** Test preamble reads all ini values needed for test, these are:
+ 	NumCipherSuites: (int) The number of cipher suit to be included in client hello message.
+   	CipherSuiteX: (hex) individual cipher suite to be included in client hello message.
+	WebAddress: (string) address of the test server could be decimal doted or human readable.
+	WebPage: (string) Test page to be requested to test server.
+	PortNum: (int) listening port used by test server.
+	ExpectedFinalCipherSuit: (hex) The cipher suite that is expected to be adopted on hnadshake.
+	UsePsk: (Bool) Use to indicate if optional PSK cipher suites are to be included in list 
+	of cipher suites send client hello message. 	
+	*/
+TVerdict CHandShakeStep::doTestStepPreambleL()
+	{
+	// Reads cipher suites to be sent in client hello message.
+	iBufCipherSuitesFromIni = ReadCipherSuitesL();
+
+	// Reads web address, this value is mandatory.
+	TPtrC   webAddress;
+	if(GetStringFromConfig(ConfigSection(), KWebAddress, webAddress))
+		{
+		iConnectSettings.iAddress = webAddress;
+		}
+	else
+		{
+		ERR_PRINTF1(_L("Failed to read web address value from INI file."));
+		User::Leave(KErrNotFound);
+		}
+
+	// Reads page web to be requested, this value is mandatory
+	TPtrC   page;
+	if(GetStringFromConfig(ConfigSection(), KWebPage, page))
+		{
+		iConnectSettings.iPage.Copy(page) ;
+		}
+	else
+		{
+		ERR_PRINTF1(_L("Failed to read page value from INI file."));
+		User::Leave(KErrNotFound);
+		}
+
+	// Reads port, this value is mandatory
+	TInt   portNum;
+	if(GetIntFromConfig(ConfigSection(), KPortNum, portNum))
+		{
+		iConnectSettings.iPortNum = portNum;
+		}
+	else
+		{
+		ERR_PRINTF1(_L("Failed to read Port Number from INI file"));
+		User::Leave(KErrNotFound);
+		}
+
+	// Reads expected final cipher suits, mandatory value
+	TInt cipher;	
+	if(GetHexFromConfig(ConfigSection(), KExpectedFinalCipher, cipher))
+		{
+		iExpectedFinalCipher = cipher;
+		}
+	else
+		{
+		ERR_PRINTF1(_L("Failed to read Expect final cipher value from INI file."));
+		User::Leave(KErrNotFound);
+		}
+		
+	// Reads expected set cipher suites error, optional value
+	TInt expectedSetSuitesError;	
+	if(GetIntFromConfig(ConfigSection(), KExpectedSetCipherError, expectedSetSuitesError))
+		{
+		iExpectedSetSuitesError = expectedSetSuitesError;
+		}
+	else
+		{
+		iExpectedSetSuitesError = KErrNone; 
+		}
+		
+	// Reads expected handshake  error, optional value
+	TInt expectedHandshakeError;	
+	if(GetIntFromConfig(ConfigSection(), KExpectedHandshakeError, expectedHandshakeError))
+		{
+		iExpectedHandshakeError = expectedHandshakeError;
+		}
+	else
+		{
+		iExpectedHandshakeError = KErrNone; 
+		}
+		
+
+	// Initialises send and receive buffers
+	iSndBuffer.CreateL(KSendBufferSize);
+	iRcvBuffer.CreateL(KReceiveBufferSize);
+	iRcvPage.CreateL(KReceiveBufferSize * 8); // Assumes 8 packages will be enough
+		
+	// Reads PSK options (optional)
+	TBool option;	
+	if(GetBoolFromConfig(ConfigSection(), KUsePsk, option))
+		{
+		iUsePsk = option;
+		}
+	else
+		{
+		iUsePsk = EFalse;
+		} 
+		
+	// Reads Null cipher options (optional)
+ 	TBool nullCipher;	
+	if(GetBoolFromConfig(ConfigSection(), KUseNullCipher, nullCipher))
+		{
+		iUseNullCipher = nullCipher;
+		}
+	else
+		{
+		iUseNullCipher = EFalse;
+		}  
+	
+	// Read server names from INI file.	
+	iServerNamesArray = ReadServerNamesL();
+		
+	return EPass;
+	}
+
+TVerdict CHandShakeStep::doTestStepL()
+	{
+	doTestL();
+	return TestStepResult();
+	}
+
+
+TVerdict CHandShakeStep::doTestL()
+	{
+	TVerdict testResult;
+    SetTestStepResult(EFail); 
+
+	// Instantiates scheduler
+ 	iSched=new(ELeave) CActiveScheduler; 
+    CleanupStack::PushL(iSched);  
+	CActiveScheduler::Install(iSched);
+	
+	// Initialises and connects the RSocket
+	ConnectL();
+    
+	// Creates active tester object which will deal will CSecureSocket instance 
+	iActiveObjTest = new (ELeave) CHandShakeTesterActive(Logger());
+	CleanupStack::PushL(iActiveObjTest);
+	
+	// Creates secure socket and start client handshake.
+ 	testResult = iActiveObjTest->DoSecureConnectionTestL(this);
+	
+	// Deletes and closes all production code been tested.
+ 	CloseConnection();
+
+	CleanupStack::PopAndDestroy(iActiveObjTest);
+	iActiveObjTest = NULL;
+	CleanupStack::PopAndDestroy(iSched);
+	iSched=NULL;
+    
+    SetTestStepResult(testResult);
+	return TestStepResult();
+	}
+
+
+void  CHandShakeStep::SetPskL()
+	{
+
+	if(iUsePsk)
+		{
+		TPckgBuf<MSoPskKeyHandler *> pskConfigPkg;
+		pskConfigPkg() = this;
+		User::LeaveIfError(iTlsSocket->SetOpt(KSoPskConfig, KSolInetSSL, pskConfigPkg));
+		}
+
+	}	
+	
+void  CHandShakeStep::SetNullCipherL()
+	{
+	
+		if(iUseNullCipher)
+ 		{
+ 		User::LeaveIfError(iTlsSocket->SetOpt(KSoEnableNullCiphers, KSolInetSSL, ETrue));
+ 		}
+	
+	}
+
+
+void CHandShakeStep::CloseConnection()
+	{
+
+	// Clean up
+	iSocket.CancelAll();
+	if(iTlsSocket)
+		{
+		iTlsSocket->CancelAll();
+		iTlsSocket->Close();
+		delete iTlsSocket;
+		iTlsSocket =0;
+		}
+
+	iSocket.Close();
+
+	}
+
+	
+void CHandShakeStep::ConnectL()
+	{
+
+	TRequestStatus rs;
+	RHostResolver hostResolver;
+	
+	// Connect the socket server
+	User::LeaveIfError( iSocketServ.Connect());	
+	
+//	User::LeaveIfError( iSocketServ.Connect());	// debug
+
+	// Interpret server address
+	if (iInetAddr.Input(iConnectSettings.iAddress) != KErrNone)
+		// Success if already in dotted-decimal format
+		{
+		// Connect to a host resolver (for DNS resolution) - happens sychronously
+		TInt retVal = hostResolver.Open( iSocketServ, KAfInet, KProtocolInetTcp);
+		
+		if(retVal != KErrNone)
+			{
+			ERR_PRINTF2(_L("Failed to open host resolver, Error:%d"),retVal);
+			User::Leave(KErrGeneral);
+			} 	 
+
+		CleanupClosePushL(hostResolver);
+
+		// Try to resolve symbolic name
+		TNameEntry nameEntry;
+
+		retVal = hostResolver.GetByName( iConnectSettings.iAddress, nameEntry );
+		if(retVal != KErrNone)
+			{
+			ERR_PRINTF2(_L("Failed to get name from host resolver, Error:%d"),retVal);
+			User::Leave(KErrGeneral);
+			} 
+
+		TSockAddr sockAddr = nameEntry().iAddr;
+		iInetAddr = iInetAddr.Cast( sockAddr );
+		
+		CleanupStack::PopAndDestroy(&hostResolver); 
+		}
+	// Store other connection parameters
+	iInetAddr.SetPort( iConnectSettings.iPortNum );
+
+	// Open a TCP socket
+	User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) );	
+
+	// Connect to the server, asynchronously
+	iSocket.Connect( iInetAddr, rs );
+
+	User::WaitForRequest( rs );
+	// Print status	
+	if(rs.Int() != KErrNone)
+		{
+		INFO_PRINTF4(_L("Connection failed to %S port:%d Error: %d"), &iConnectSettings.iAddress, iConnectSettings.iPortNum, rs.Int() );
+		User::Leave(KErrCouldNotConnect);
+		}
+	else
+		{
+		INFO_PRINTF3(_L("Connected to %S port:%d"), &iConnectSettings.iAddress, iConnectSettings.iPortNum );
+		}
+	}
+	
+/** Read list of cipher to be included in client hello message.
+@param None
+@return HBufC8 list of cipher suites
+*/
+
+HBufC8* CHandShakeStep::ReadCipherSuitesL()
+	{
+	
+	TInt numCipherSuites;
+	TName  fCipherSuite;
+	TInt   iniCipherSuite;  
+	HBufC8* allSuites = NULL;
+		
+	if(GetIntFromConfig(ConfigSection(),KNumCipherSuites,numCipherSuites))
+		{
+		// Each cipher suite uses 2 bytes
+		allSuites = HBufC8::NewMaxL( numCipherSuites * 2);
+		TPtr8 ptr = allSuites->Des(); 
+	
+		for(TInt index = 1;index <= numCipherSuites ; ++index)
+			{
+			fCipherSuite.Format(_L("%S%d"), &KCipherSuiteBase, index);
+			if(GetHexFromConfig(ConfigSection(), fCipherSuite,iniCipherSuite))
+				{
+				// Two bytes for each cipher suite
+				ptr[(index - 1) * 2] =	( ( iniCipherSuite & 0xFF00) >> 8);
+				ptr[( (index - 1) * 2 ) + 1] =	iniCipherSuite & 0xFF;
+				}
+			}
+		}
+	
+	return allSuites;
+	}  
+
+/** Read list of server to be included in client hello message form INI file.
+@param None
+@return CDesC8ArrayFlat list of server names
+*/
+
+
+CDesC8ArrayFlat * CHandShakeStep::ReadServerNamesL()
+	{
+ 
+	TInt numServerNames;
+	TName  fServerName;
+	TPtrC  serverName;  
+	CDesC8ArrayFlat* allServerNames = NULL;   
+	
+	if(GetIntFromConfig(ConfigSection(),KNumServerNames,numServerNames))
+		{
+		
+		if( numServerNames >0)
+			{
+			iUseServerNames = ETrue;
+			
+			allServerNames = new(ELeave) CDesC8ArrayFlat(1);
+			CleanupStack::PushL(allServerNames);
+			
+			// Reads each server name and appends it to array.
+			for(TInt index = 1;index <= numServerNames ; ++index)
+				{
+				fServerName.Format(_L("%S%d"), &KServerNameBase, index);
+				if(GetStringFromConfig(ConfigSection(), fServerName, serverName))
+					{
+					HBufC8 *serverName8bited = HBufC8::NewMaxLC(serverName.Length());
+					serverName8bited->Des().Copy(serverName);
+		 			allServerNames->AppendL(serverName8bited->Des());
+		 			CleanupStack::PopAndDestroy(serverName8bited);
+					}
+				else
+					{
+					INFO_PRINTF2(_L("Could not found ServerName %d from INI file"), index );
+					User::Leave(KErrGeneral);	
+					}
+				}
+			CleanupStack::Pop(allServerNames);		
+			}
+	
+		}
+	else
+		{
+		iUseServerNames = EFalse; 	
+		}
+	 
+	return allServerNames;
+	}  
+	
+	
+