--- /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;
+ }
+