datacommsserver/esockserver/test/TS_MultiHoming/TS_MultiHomingSuite.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/test/TS_MultiHoming/TS_MultiHomingSuite.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,558 @@
+// Copyright (c) 2002-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:
+// This defines the CTS_MultiHomingSuite class which is the 
+// container class for the TS_MultiHomingStep-derived test steps
+// 
+//
+
+/**
+ @file
+*/
+
+#include "TS_MultiHomingSuite.h"
+#include "TS_RConnectionStart.h"
+#include "TS_RConnectionClose.h"
+#include "TS_RConnectionStop.h"
+#include "TS_TestConnection.h"
+#ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+#include "ts_testincomming.h"
+#endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+#include "TS_CopyComDbFile.h"
+#include "TS_ShowConnections.h"
+#include "TS_ResolveName.h"
+#include "TS_ResolveAddress.h"
+#include "TS_GetConnectionInfo.h"
+#include "TS_CheckLinkLocalSame.h"
+#include "TS_Delay.h"
+#include <e32cons.h>
+#include <in_sock.h>
+#include <in_iface.h>
+#include <nifman.h>
+					  
+
+EXPORT_C CTS_MultiHomingSuite* NewTS_MultiHomingSuite( void ) 
+/** Polymorphic interface, exported ordinal 1.  Called by scheduletest
+ * and used to instantiate the suite
+ * @return A pointer to the created CTS_MultiHomingSuite object
+ */
+    {
+	CTS_MultiHomingSuite* ts = 0;
+	TRAPD(err,ts = new (ELeave) CTS_MultiHomingSuite);
+	if (err == KErrNone)
+		return ts;
+	return 0;
+    }
+
+CTS_MultiHomingSuite::~CTS_MultiHomingSuite()
+/** 
+ * Destructor has to clean up any TConnDetails left hanging around
+ * 
+ */
+	{
+	delete iScheduler;
+	}
+
+void CTS_MultiHomingSuite::AddTestStepL( CTS_MultiHomingStep* ptrTestStep )
+/**
+ * Adds a test step to the test suite object, using the base class method
+ * @param ptrTestStep A pointer to the test step to be added
+ * @exception Can leave
+ */
+	{
+	ptrTestStep->iOwnerSuite = this; 
+	CTestSuite::AddTestStepL(ptrTestStep);
+	}
+
+void CTS_MultiHomingSuite::InitialiseL( void )
+/**
+ * Effective second-phase constructor.  Creates all suite test steps
+ * and associates them with the suite.
+ */
+	{
+	// Load the serial drivers
+	TInt ret = User::LoadPhysicalDevice(PDD_NAME);
+	if ( KErrNone != ret && KErrAlreadyExists != ret )
+		{
+		User::Leave( ret );
+		}
+		
+	ret = User::LoadLogicalDevice(LDD_NAME);
+	if ( KErrNone != ret && KErrAlreadyExists != ret )
+		{
+		User::Leave( ret );
+		}
+
+ 	// When bootstrapping C32 we have to avoid the PhBkSyncServer being started, since
+ 	// it needs a different CommDB
+ 	_LIT(KPhbkSyncCMI, "phbsync.cmi");
+    ret = StartC32WithCMISuppressions(KPhbkSyncCMI);
+	if ( KErrNone != ret && KErrAlreadyExists != ret )
+		{
+		User::Leave( ret );
+		}
+
+	//Make the scheduler...
+	
+	iScheduler=new(ELeave) CEnhancedScheduler();
+	CEnhancedScheduler::Install(iScheduler);
+	
+
+	// Add Test steps	
+	AddTestStepL( new(ELeave) CTS_RConnectionStart );
+	AddTestStepL( new(ELeave) CTS_RConnectionClose );
+	AddTestStepL( new(ELeave) CTS_RConnectionStop  );
+	AddTestStepL( new(ELeave) CTS_TestConnection   );
+
+#ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+	AddTestStepL( new(ELeave) CTS_TestIncomming   );
+#endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+	AddTestStepL( new(ELeave) CTS_ShowConnections  );
+	AddTestStepL( new(ELeave) CTS_ResolveName );
+	AddTestStepL( new(ELeave) CTS_ResolveAddress );
+	AddTestStepL( new(ELeave) CTS_GetConnectionInfo );
+	AddTestStepL( new(ELeave) CTS_CheckLinkLocalSame );
+	AddTestStepL( new(ELeave) CTS_CopyComDbFile );
+	AddTestStepL( new(ELeave) CTS_Delay );
+	}
+
+
+TPtrC CTS_MultiHomingSuite::GetVersion( void )
+/**
+ * Give version information back to Schedultest
+ * @return The descriptor of the version
+ */
+	{
+	return KTxtVersion();
+	}
+
+
+TInt CTS_MultiHomingSuite::GetConnIndex(const TDesC& aName)
+/**
+ * Gets the array index of the name passed in
+ * @param aName Descriptor containing the connection name to match
+ * @return The index, or KErrNotFound
+ */
+	{
+	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
+		{
+		if (iConnections[i].MatchName(aName))
+			return i;
+		}
+	return KErrNotFound;
+	}
+
+
+TConnDetails *CTS_MultiHomingSuite::GetNewTConnection( )
+/**
+ * Retreive 
+ *
+ */
+	{
+	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
+		{
+		if (iConnections[i].iName.Length() == 0)
+			return &iConnections[i];
+		}
+	return 0;
+	}
+
+TInt CTS_MultiHomingSuite::AddConnection(const TConnDetails& aConn)
+/**
+ * Appends a connection to the array of connections in the suite
+ * @param aName Reference to the object to pass in
+ * @return System wide error code 
+ */
+	{
+	TInt err= KErrNone;			// Check the name doesn't already exist
+	TInt connIndex = GetConnIndex(aConn.iName);
+	if(KErrNotFound == connIndex)
+		{
+		//err = iConnections.Append(aConn);
+		}
+	else
+		{
+		err = KErrAlreadyExists;
+		_LIT(KMultipleConns, "Connection has already been started. Check configuration files.");
+		LogExtra((TText8*)__FILE__, __LINE__, ESevrInfo, KMultipleConns);
+		}
+
+	return err;
+	}
+
+TConnDetails *CTS_MultiHomingSuite::GetTConnection(const TDesC& aName)
+/**
+ * Returns the TConnection object for a specific connection
+ * @param aName Name of connection to look up
+ * @return The RConnection object
+ */
+
+	{
+	TInt err= KErrNone;
+	err = GetConnIndex(aName);
+	if (err == KErrNotFound)
+		{
+		//User::Panic(KTxtSuiteName, err);
+		return 0;
+		}
+	return &iConnections[err];
+	}
+	
+RConnection *CTS_MultiHomingSuite::GetRConnection(const TDesC& aName)
+/**
+ * Returns the RConnection object for a specific connection
+ * @param aName Name of connection to look up
+ * @return The RConnection object
+ */
+    {
+	TInt err= KErrNone;
+	err = GetConnIndex(aName);
+	if (err == KErrNotFound)
+		{
+		//User::Panic(KTxtSuiteName, err);
+		return 0;
+		}
+	return &iConnections[err].iConnection;
+	}
+
+RSocketServ *CTS_MultiHomingSuite::GetRSocketServ(const TDesC& aName)
+/**
+ * Returns the RSocketServ object for a specific connection
+ * @param aName Name of connection to look up
+ * @return The RSocketServ object
+ */
+	{
+	TInt connIndex = -1;
+
+	connIndex = GetConnIndex(aName);
+	if (connIndex < 0)
+		{
+		return 0;
+		}
+	return &iConnections[connIndex].iSocketServ;
+	}
+
+
+TInt CTS_MultiHomingSuite::CloseConnection(const TDesC& aName)
+/** 
+ * Closes a connection and removes it from the array
+ * @param aName The name of the connection to close
+ * @return System wide error code
+ */
+	{
+	TInt index= KErrNone;
+	index= GetConnIndex(aName);
+	if (index != KErrNotFound)
+		{
+		if (iConnections[index].iClients == 0)		// No open sockets, so can close
+			{
+			if(iConnections[index].iConnectionType 
+				!= TConnDetails::implicitConn)
+				{
+				iConnections[index].iConnection.Close();
+				}
+			else
+				{
+				iConnections[index].iSocket.Close();
+				}
+
+			iConnections[index].iSocketServ.Close();
+			iConnections[index].iName.Zero();
+			return KErrNone;
+			}
+		return KErrInUse;
+		}
+	return index;
+	}
+
+
+TInt CTS_MultiHomingSuite::StopConnection(const TDesC& aName)
+/** 
+ * Closes a connection and removes it from the array
+ * @param aName The name of the connection to close
+ * @return System wide error code
+ */
+	{
+	TInt index= KErrNone;
+	index= GetConnIndex(aName);
+	if (index != KErrNotFound)
+		{
+		if (iConnections[index].iClients == 0)		// No open sockets, so can close
+			{
+			if(iConnections[index].iConnectionType 
+				!= TConnDetails::implicitConn)
+				{
+				iConnections[index].iConnection.Stop();	//< Any connections present killed
+				}
+			else
+				{
+				iConnections[index].iSocket.Close();
+				}
+
+			iConnections[index].iSocketServ.Close();
+			iConnections[index].iName.Zero();
+			return KErrNone;
+			}
+		return KErrInUse;
+		}
+	return index;
+	}
+
+
+inline void RemoveScopeFromAddress(TName& address)
+	{
+	TChar percent('%');
+	TInt percentIndex = address.Locate(percent);
+	
+	if( percentIndex >= 0 )
+		{
+		address.SetLength(percentIndex);
+		}
+	}
+
+TInt CTS_MultiHomingSuite::DisplayConnectionDetailsL()
+/**
+ * Displays the IP interfaces that are currently in the system
+ * @return number of non loopback interfaces
+ */
+	{
+	TInt err = KErrNone;
+	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
+		{
+		if(iConnections[i].iName.Length() == 0)
+			{
+			continue;
+			}
+		_LIT (KConnLogString, "Name [%S], RConnection[%x], RSocketServ[%x]");
+		Log(KConnLogString, &iConnections[i].iName,
+							&iConnections[i].iConnection,
+							&iConnections[i].iSocketServ);
+	
+		}
+
+	TAutoClose<RSocketServ> ss;
+	err = ss.iObj.Connect();
+	ss.PushL();
+
+	TAutoClose<RSocket> sock;
+	err = sock.iObj.Open(ss.iObj, _L("udp"));
+
+	sock.PushL();
+
+	User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
+
+	TProtocolDesc in;
+	User::LeaveIfError(sock.iObj.Info(in));
+	//LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE START"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild);
+
+
+	TPckgBuf<TSoInetInterfaceInfo> info;
+	
+	err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+	// The first interface is always empty
+	err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+	TInt numberOfInterfaces = 0;
+	while(err == KErrNone)
+		{
+		// Skip loopback interfaces
+		if(info().iFeatures & KIfIsLoopback || info().iState != EIfUp) 
+			{
+			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+			continue;
+			}
+
+		
+		TBuf <MAX_LOG_LINE_LENGTH> LineBuf;
+		
+
+		LineBuf.AppendFormat(_L("%S: Tag: \"%S\" is ")
+					,&info().iName
+					,&info().iTag);
+
+		LineBuf.Append(info().iState == EIfPending ? _L("PENDING") :
+					   info().iState == EIfUp      ? _L("UP")      :
+					   info().iState == EIfDown    ? _L("DOWN")    :
+					   info().iState == EIfBusy    ? _L("BUSY")    :
+					   _L("UNDEFINED_STATE"));
+		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
+
+		LineBuf.Zero();
+		LineBuf.AppendFormat(_L("%S: "), &info().iName);
+
+		LineBuf.AppendFormat(_L("Mtu: %d Speed: %d "), info().iMtu, info().iSpeedMetric);
+		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
+
+		LineBuf.Zero();
+		LineBuf.AppendFormat(_L("%S: "), &info().iName);
+
+
+		TName address;
+		info().iAddress.Output(address);
+		LineBuf.Append(_L("Address "));
+		//RemoveScopeFromAddress(address);
+		LineBuf.Append(address);		
+		TName netmask;
+		info().iNetMask.OutputWithScope(netmask);
+		LineBuf.Append(_L("/"));
+		LineBuf.Append(netmask);
+		info().iAddress.IsLinkLocal() ? LineBuf.Append(_L("   is Link local")) :
+		info().iAddress.IsSiteLocal() ? LineBuf.Append(_L("   is Site local")) :
+		LineBuf.Append(_L("     is Global"));
+
+
+		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
+		LineBuf.Zero();
+		LineBuf.AppendFormat(_L("%S: "), &info().iName);
+
+
+		info().iBrdAddr.Output(address);
+		//RemoveScopeFromAddress(address);
+		TChar colon(':');
+		// Assume single IPv4 addres per interface
+		if(address.Locate(colon) < 0)
+			{
+			numberOfInterfaces++;
+			}
+		// 2 == :: ie zeros
+		if(address.Length() > 3)
+			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Broadcast address %S"), &info().iName, &address);
+		info().iDefGate.Output(address);
+		//RemoveScopeFromAddress(address);
+		if(address.Length() > 3)
+			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Default gateway %S"), &info().iName, &address);
+		info().iNameSer1.Output(address);
+		//RemoveScopeFromAddress(address);
+		if(address.Length() > 3)
+			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Primary DNS %S"), &info().iName, &address);
+		info().iNameSer2.Output(address);
+		//RemoveScopeFromAddress(address);
+		if(address.Length() > 3)
+			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Secondary DNS %S"), &info().iName, &address);
+
+	
+
+		if(info().iFeatures & KIfIsLoopback) 
+			{
+			LineBuf.Append(_L(" LOOPBACK"));
+			}
+		if(info().iFeatures & KIfIsDialup)
+			{
+			LineBuf.Append(_L(" DIALUP"));
+			}
+		if(info().iFeatures & KIfIsPointToPoint)
+			{
+			LineBuf.Append(_L(" POINTTOPOINT"));
+			}
+		if(info().iFeatures & KIfCanBroadcast)
+			{
+			LineBuf.Append(_L(" BROADCAST"));
+			}
+		
+		if(info().iFeatures & KIfCanMulticast)
+			{
+			LineBuf.Append(_L(" MULTICASTCAST"));
+			}
+		if(info().iFeatures & KIfCanSetMTU)
+			{
+			LineBuf.Append(_L(" SETMTU"));   
+			}
+		if(info().iFeatures & KIfCanSetHardwareAddr)
+			{
+			LineBuf.Append(_L(" CANSETHWADDR"));
+			}
+
+		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
+		LineBuf.Zero();
+
+
+		if(info().iFeatures & KIfHasHardwareAddr)
+			{
+			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L(" Hardware address "));		
+			TUint j;
+			for(j=sizeof(SSockAddr) ; j<sizeof(SSockAddr)+6 ; ++j)
+				{
+				if(j<(TUint)info().iHwAddr.Length())
+					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%02X"), info().iHwAddr[j]);
+				else
+					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("??"));
+				if(j<sizeof(SSockAddr)+5)
+				   LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("-"));
+				else
+					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L(""));
+				}
+			}
+			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+			
+		}
+		
+	sock.Pop();
+	ss.Pop();
+	
+//	LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE LIST END"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild);
+
+	return numberOfInterfaces;
+	}
+
+	
+/**
+ * Compares first two non-loopback link-local addresses
+ * @return TRUE if equal else FALSE
+ */
+	TBool CTS_MultiHomingSuite::CompareLinkLocalAddressesL()
+	{
+		
+		TName  addresses[2];
+		TAutoClose<RSocketServ> ss;
+		TInt err = ss.iObj.Connect();
+		ss.PushL();
+		TAutoClose<RSocket> sock;
+		err = sock.iObj.Open(ss.iObj, _L("udp"));
+		sock.PushL();
+
+		User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
+		
+		TPckgBuf<TSoInetInterfaceInfo> info;
+		err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+		// The first interface is always empty
+		err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+		
+		TInt i = 0;		
+		while((i < 2) && (err== KErrNone))
+			{
+			// Skip loopback interfaces
+			if(info().iFeatures & KIfIsLoopback) 
+				{
+				err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+				continue;
+				}		
+							
+			if (info().iAddress.IsLinkLocal())
+				{
+				//TName address;
+				//addresses[i].FillZ();				
+				info().iAddress.Output(addresses[i]);						
+				RemoveScopeFromAddress(addresses[i]);
+				i++;
+				}
+
+			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
+			}
+
+		sock.Pop();
+		ss.Pop();
+		
+		if ((i == 2) && (addresses[0].Compare(addresses[1]) == 0))					
+			return TRUE;
+		return FALSE;
+	}
+