diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_RConnectionStep.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_RConnectionStep.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,2146 @@ +// 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 contains TE_RConnectionStep class which is +// the base class for all the RConnection multihoming test steps. +// Contains methods which simplify the API to RConnection, RSocket and +// RHostResolver to be used by derived classes. This abstraction means +// that the API can continue to evolve as it has done for a while without +// impacting a large number of test cases - just alter this parent class. +// +// + +/** + @file +*/ +#include "TE_RConnectionStep.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SYMBIAN_OLD_EXPORT_LOCATION +#include +#else +//after the header file relocation this header won't be exported, so it needs to be a user include. +#include "naptinterface.h" +#endif + +#include + +_LIT(KSimtsyName,"SIM"); + +TE_RConnectionStep::TE_RConnectionStep() +/** + * Constructor for TS_RConnectonStep(). Does nothing. + * @param none + * @return doesn't it is a constructor + */ +{ +} + +TE_RConnectionStep::~TE_RConnectionStep() +/** + * Destructor for TE_RConnectionStep(). Does nothing. + */ +{ + CActiveScheduler::Install(NULL); + delete iScheduler; +} + +enum TVerdict TE_RConnectionStep::doTestStepPreambleL(void) +/** + * Preamble called before every single test case which is derived from TE_RConnectionStep (unless overridden of course). Sets up addresses and other values to be used by the test code proper. Waits for any remaining interfaces from previous tests to close. + * @param none + * @return success (EPass) or failure (EFail) of initialisation + */ +{ + enum TVerdict result = EPass; + _LIT(KPhbkSyncCMI, "phbsync.cmi"); + if (StartC32WithCMISuppressions(KPhbkSyncCMI) != KErrNone) + { + return EFail; + } + iScheduler = new(ELeave) CActiveScheduler; + CActiveScheduler::Install(iScheduler); + /* + * Load the config from the .ini file + */ + + if (KErrNone != ReadIniFile()) + result = EFail; + + iDummyNifSendAddr.SetAddress(KDummyNifLocalAddressBase + KDummyHungryNifReservedHostId); + iDummyNifSendAddr.SetPort(iEchoPortNum); + iHungryNifSendAddr.SetAddress(KDummyNifLocalAddressBase + KDummyHungryNifReservedHostId); + iHungryNifSendAddr.SetPort(iEchoPortNum); + + _LIT(KNaptStatusCheck, "On"); + if (iNaptStatus.Compare(KNaptStatusCheck)!=0) + { + // Wait for all of the interfaces to close down + RSocketServ ss; + + ss.Connect(); + CleanupClosePushL(ss); + + if (KErrNone != WaitForAllInterfacesToCloseL(ss)) + { + INFO_PRINTF1(_L("Previous test case has left connections up that have not closed. Stopping them.")); + TBuf<200> errDesc; + TInt err; + if ((err = ESockTestUtils::StopAllInterfaces(errDesc)) == KErrNone) + result = EPass; + else + { + INFO_PRINTF3(_L("StopAllInterfaces() err=%d\n%S"), err, &errDesc); + result = EFail; + } + } + ss.Close(); + CleanupStack::Pop(); + } + + return result; +} + +enum TVerdict TE_RConnectionStep::doTestStepPostambleL(void) +{ + + if( iStatus && iStatus->IsActive() ) + { + iStatus->Cancel(); + } + delete iStatus; + iStatus = NULL; + CActiveScheduler::Install(NULL); + REComSession::FinalClose(); + + return EPass; +} + +TInt TE_RConnectionStep::ReadIniFile(void) +/** + * Opens the .ini file, reads the contents into some class members and then closes the file again + * @return system wide error code + */ +{ + TInt result = KErrNone; + + TPtrC filename(_L("c:\\rconnectiontest.ini")); + TBuf<64> tempBuf; // 16 is enough for an IP addr and the separating dots + TPtrC temp(0,NULL); + + + // this opens the file and loads everything in + // LoadConfig(filename); + + // set the IAP values in the class members + _LIT(KIapSection, "IAP"); + _LIT(KDummyNifIapKey, "DummyNifIapNumber"); + _LIT(KNtRasIapOnlyShortTimerKey, "DummyNifOnlyShortTimerIapNumber"); + _LIT(KDummyNifLongTimeoutIapKey, "DummyNifLongTimeoutIapNumber"); + _LIT(KDummyNifTwoBinderIapKey, "DummyNifTwoBinderIapNumber"); + _LIT(KHungryNifLongTimeoutIapKey, "HungryNifLongTimeoutIapNumber"); + _LIT(KHungryNifIapKey, "HungryNifIapNumber"); + _LIT(KDefaultIapKey, "DefaultIapNumber"); + _LIT(KBadNtRasIapKey, "BadNtRasIapNumber"); + _LIT(KMissingNifIapKey, "MissingNifIapNumber"); + _LIT(KTestNifIapKey, "TestNifIapNumber"); + _LIT(KDummyNifAgentIap, "DummyNifAgentIapNumber"); + _LIT(KSimTSYIap, "SimTSYIapNumber"); + _LIT(KStaticDnsDynamicAddr, "StaticDnsDynamicAddr"); + + if (!(GetIntFromConfig(KIapSection, KDummyNifIapKey, iDummyNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KDummyNifLongTimeoutIapKey, iDummyNifLongTimeoutIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KDummyNifTwoBinderIapKey, iDummyNifTwoBinderIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KHungryNifLongTimeoutIapKey, iHungryNifLongTimeoutIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KHungryNifIapKey, iHungryNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KDefaultIapKey, iDefaultIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KNtRasIapOnlyShortTimerKey, iNtRasIapOnlyShortTimer))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KBadNtRasIapKey, iBadNtRasIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KMissingNifIapKey, iMissingNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KTestNifIapKey, iTestNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KDummyNifAgentIap, iDummyNifAgentIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KSimTSYIap, iSimTSYIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KStaticDnsDynamicAddr, iStaticDnsDynamicAddr))) + result = KErrNotFound; + + + // IAP numbers specifically used by the all interface notification tests + _LIT(KAinIapSection, "AINIAPs"); + _LIT(KSecondHungryNifIapKey, "SecondHungryNifNumber"); + _LIT(KThirdHungryNifIapKey, "ThirdHungryNifNumber"); + _LIT(KSecondDummyNifIapKey, "SecondDummyNifNumber"); + _LIT(KThirdDummyNifIapKey, "ThirdDummyNifNumber"); + _LIT(KFourthDummyNifIapKey, "FourthDummyNifNumber"); + _LIT(KFifthDummyNifIapKey, "FifthDummyNifNumber"); + _LIT(KFNaptPublicIapKey, "NaptPublicIapNumber"); + _LIT(KFNaptPrivateIapKey, "NaptPrivateIapNumber"); + + + if (!(GetIntFromConfig(KAinIapSection, KSecondHungryNifIapKey, iSecondHungryNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KAinIapSection, KThirdHungryNifIapKey, iThirdHungryNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KAinIapSection, KSecondDummyNifIapKey, iSecondDummyNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KAinIapSection, KThirdDummyNifIapKey, iThirdDummyNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KAinIapSection, KFourthDummyNifIapKey, iFourthDummyNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KAinIapSection, KFifthDummyNifIapKey, iFifthDummyNifIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KFNaptPublicIapKey, iNaptPublicIap))) + result = KErrNotFound; + if (!(GetIntFromConfig(KIapSection, KFNaptPrivateIapKey, iNaptPrivateIap))) + result = KErrNotFound; + + // set the timeout values in the class members + _LIT(KTimeoutSection, "Timeouts"); + _LIT(KShortTimeoutKey, "ShortTimeout"); + _LIT(KMediumTimeoutKey, "MediumTimeout"); + _LIT(KLongTimeoutKey, "LongTimeout"); + + if (!(GetIntFromConfig(KTimeoutSection, KShortTimeoutKey, iShortTimeout))) + result = KErrNotFound; + if (!(GetIntFromConfig(KTimeoutSection, KMediumTimeoutKey, iMediumTimeout))) + result = KErrNotFound; + if (!(GetIntFromConfig(KTimeoutSection, KLongTimeoutKey, iLongTimeout))) + result = KErrNotFound; + + // other general set up stuff + _LIT(KGeneralSection, "General"); + _LIT(KInterfaceName, "Interface"); + if (!(GetStringFromConfig(KGeneralSection, KInterfaceName, temp))) + result = KErrNotFound; + iInterfaceName.Copy(temp); + + _LIT(KNameServerAddr, "NameServerAddr"); + if (!GetStringFromConfig(KGeneralSection, KNameServerAddr, temp)) + result = KErrNotFound; + iNameServerAddr.Input(temp); + + _LIT(KEchoPortKey, "EchoPort"); + if (!(GetIntFromConfig(KGeneralSection, KEchoPortKey, iEchoPortNum))) + result = KErrNotFound; + _LIT(KNaptTestServerPort, "NaptTestServerPort"); + if (!(GetIntFromConfig(KGeneralSection, KNaptTestServerPort, iNaptTestServerPort))) + result = KErrNotFound; + + // set the address which we should connect TCP sockets to (addr of TCP echo server) + _LIT(KTcpConfigSection, "TCP Config"); + _LIT(KTcpSendAddrKey, "TcpSendAddress"); + if (!GetStringFromConfig(KTcpConfigSection, KTcpSendAddrKey, temp)) + result = KErrNotFound; + iEchoServerAddr.Input(temp); + // set it's port to the echo port + iEchoServerAddr.SetPort(iEchoPortNum); + + // Napt + _LIT(KNaptTestServer, "NaptTestServer"); + if (!GetStringFromConfig(KGeneralSection, KNaptTestServer, temp)) + result = KErrNotFound; + iNaptTestServAddr.Input(temp); + // set it's port to the NaptTestServer port + iNaptTestServAddr.SetPort(iNaptTestServerPort); + + // the name which we will attempt to resolve many many times + _LIT(KTestNameKey, "TestName"); + if (!GetStringFromConfig(KTcpConfigSection, KTestNameKey, temp)) + result = KErrNotFound; + iTestName = temp; + + // the address which we will pass in when using GetByAddress() + _LIT(KLookupAddressKey, "LookupAddress"); + if (!GetStringFromConfig(KGeneralSection, KLookupAddressKey, temp)) + result = KErrNotFound; + iLookupAddress.Input(temp); + + _LIT(KNaptStatus, "NaptStatus"); + if (!GetStringFromConfig(KGeneralSection, KNaptStatus, iNaptStatus)) + result = KErrNotFound; + + return result; +} + +TInt TE_RConnectionStep::OpenSocketServer(RSocketServ& ss) +/** + * Opens the socket server that is pointed to + * @param ss the socket server to open + * @return system wide error code + */ + { + INFO_PRINTF1(_L("Opening Socket server")); + return (ss.Connect()); + } + +void TE_RConnectionStep::CloseSocketServer(RSocketServ& ss) +/** + * Closes the socket server that is pointed to + * @param ss the socket server to close + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Closing Socket server")); + ss.Close(); // Close() inherited from RHandleBase? +} + +TInt TE_RConnectionStep::OpenConnection(RConnection& conn, RSocketServ& ss) +/** + * Open the connection using the socket server too + * @param conn the connection to open + * @param ss the socket server within which the connection is to be opened + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Opening Connection")); + return (conn.Open(ss)); +} + +TInt TE_RConnectionStep::OpenConnection(RConnection& conn, RSocketServ& ss, TName& name) +/** + * Open the connection (passing the name provided) + * @param conn - the connection to open + * @param ss - the socket server within which the connection is to be opened + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Opening Connection")); + return (conn.Open(ss, name)); +} + +TInt TE_RConnectionStep::StartConnection(RConnection& conn) +/** + * Start a connection using the default comm db settings + * @param conn the connection to start + * @return system wide error code + */ +{ + TRequestStatus status; + conn.Start(status); + INFO_PRINTF1(_L("Starting Connection")); + User::WaitForRequest(status); + return status.Int(); +} + +TInt TE_RConnectionStep::StartConnectionSynchronous(RConnection& conn) +/** + * Start a connection using the default comm db settings (using the synchronous call) + * @param conn - the connection to start + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Starting Connection")); + return (conn.Start()); +} + +void TE_RConnectionStep::StartConnectionAsynchronous(RConnection& conn, TRequestStatus& status) +/** + * Start a connection using the default comm db settings (returning before it completes) + * @param conn - the connection to start + * @param system wide error code + */ +{ + INFO_PRINTF1(_L("Starting Connection")); + conn.Start(status); +} + +TInt TE_RConnectionStep::StartConnectionWithOverrides(RConnection& conn, TInt iap) +/** + * Start a connection on the IAP as specified by the param, do this by + * building some database overrides. + * @param conn - the connection to start + * @param iap - which IAP to create the connection over + * @return system wide error code + */ +{ + TRequestStatus status; + + TCommDbConnPref prefs; + prefs.SetIapId(iap); + prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); + conn.Start(prefs, status); + INFO_PRINTF1(_L("Starting Connection with over rides")); + User::WaitForRequest(status); + + return status.Int(); +} + +TInt TE_RConnectionStep::StartConnectionWithOverridesSynchronous(RConnection& conn, TInt iap) +/** + * Start a connection on the IAP as specified by the param, do this by building some + * database overrides. Use the synchronous start method + * @param conn - the connection to start + * @param iap - which IAP to create the connection over + * @return system wide error code + */ +{ + TCommDbConnPref prefs; + prefs.SetIapId(iap); + INFO_PRINTF1(_L("Starting Connection with over rides")); + prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); + return (conn.Start(prefs)); +} + +void TE_RConnectionStep::StartConnectionWithOverridesAsynchronous(RConnection& conn, TCommDbConnPref& aPrefs, TInt iap, TRequestStatus& status) +/** + * Start a connection on the IAP as specified by the param - return before it completes + * @param conn - the connection to start + * @param iap - which IAP to create the connection over + * @return system wide error code + */ +{ + aPrefs.SetIapId(iap); + aPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); + INFO_PRINTF1(_L("Starting Connection with over rides")); + conn.Start(aPrefs, status); +} + + + +void TE_RConnectionStep::CloseConnection(RConnection& conn) +/** + * Close a connection + * @param conn the connection to close + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Closing Connection ")); + conn.Close(); +} + + +TInt TE_RConnectionStep::StopConnection(RConnection& conn) +/** + * Force the connection to stop and remove the interface no matter what other connections are using it + * @param conn the connection to stop + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Stopping Connection ")); + return (conn.Stop()); +} + +TInt TE_RConnectionStep::EnumerateConnections(RConnection& conn, TUint& num) +/** + * Read how many connections (==interfaces?) exist at the moment + * @param conn - to be used to read the count + * @param num - on completion holds the number of connections + * @return system wide error code + */ +{ + return (conn.EnumerateConnections(num)); +} + +TInt TE_RConnectionStep::GetTimeoutValues(RConnection& conn, TTimeoutValues &timeouts) +/** + * Read the timeout values from commdb + * @param conn - the connection to read the values from + * @param timeouts - where to put the timeout vals + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Getting Timeout Values")); + TInt ret = KErrNone; + TInt tmp; + if (KErrNone != (tmp = conn.GetIntSetting(_L("ModemBearer\\LastSessionClosedTimeout"), timeouts.iShortTimeout))) + ret = tmp; + if (KErrNone != (tmp = conn.GetIntSetting(_L("ModemBearer\\LastSocketClosedTimeout"), timeouts.iMediumTimeout))) + ret = tmp; + if (KErrNone != (tmp = conn.GetIntSetting(_L("ModemBearer\\LastSocketActivityTimeout"), timeouts.iLongTimeout))) + ret = tmp; + + return ret; +} + +TInt TE_RConnectionStep::AttachNormal(RConnection& conn, const TDesC8& info) +/** + * Attach the connection supplied to the one described by the info + * @param conn - the connection to be attached to something + * @param info - the details of the connection to attach to + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Attach Normal")); + return conn.Attach(info, RConnection::EAttachTypeNormal); +} + +TInt TE_RConnectionStep::AttachMonitor(RConnection& conn, const TDesC8& info) +/** + * Attach the connection supplied to the one described by the info (as a monitor) + * @param conn - the connection to be attached to something + * @param info - the details of the connection to attach to + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Attach Monitor")); + return conn.Attach(info, RConnection::EAttachTypeMonitor); +} + +void TE_RConnectionStep::ProgressNotification(RConnection& conn, TRequestStatus& status, + TNifProgressBuf& progress, TUint aSelectedProgress) +/** + * Request notification when the progress changed to that supplied + * @param conn - the connection we are interested in the progress of + * @param status - the status variable which should be updated eventually + * @param aSelectedProgress - the progress we want + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Progress Notification ")); + conn.ProgressNotification(progress, status, aSelectedProgress); +} + +void TE_RConnectionStep::ProgressNotification(RConnection& conn, TRequestStatus& status, + TNifProgressBuf& progress) +/** + * Request notification of the next progress change + * @param conn - the connection whose status we are interested in + * @param status - the status variable that should be updated + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Progress Notification ")); + conn.ProgressNotification(progress, status); +} + +void TE_RConnectionStep::CancelProgressNotification(RConnection& conn) +/** + * Cancel the notification of progress changes + * @param conn - the connection to cancel progress notification for + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Cancel Connection Progress Notification ")); + conn.CancelProgressNotification(); +} + +TInt TE_RConnectionStep::Progress(RConnection& conn, TNifProgress& progress) +/** + * Read the current progress state + * @param conn - the connection to read the progress of + * @param progress - where to put the read progress + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Progress")); + return conn.Progress(progress); +} + +TInt TE_RConnectionStep::LastProgressError(RConnection& conn, TNifProgress& progress) +/** + * Get the last progress error + * @param conn - the connection we are interested in + * @param progress - where to put the progress value (the error) + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Connection Last Progress Error")); + return conn.LastProgressError(progress); +} + +TInt TE_RConnectionStep::GetConnectionInfo(RConnection& conn, TUint index, TDes8& aConnectionInfo) +/** + * Read back the information about a particular connection (using the enumeration functionality) + * @param conn - the connection to use to access the info + * @param index - the index of the connection we want to find out about + * @param aConnectionInfo - where to write the info into + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Get Connection info ")); + return conn.GetConnectionInfo(index, aConnectionInfo); +} + +TInt TE_RConnectionStep::GetInfo(RConnection& conn, TPckgBuf& info) +/** + * Read the info about this connection from comm db + * @param conn - the connection to read info about + * @param info - where to write the info to + * @return system wide error code + */ +{ + _LIT(KIapTableIdDes, "IAP\\Id" ); + _LIT(KIapTableIapNetworkDes, "IAP\\IAPNetwork" ); + + TInt ret = KErrNone; + ret = conn.GetIntSetting(KIapTableIdDes, info().iIapId); + + const CommsDat::TMDBElementId KIapTableIdFieldId = KCDTIdIAPRecord | KCDTIdRecordTag; + const CommsDat::TMDBElementId KTapTableIapNetworkId = KCDTIdIAPNetwork; + + if (ret == KErrNone) + { + ret = conn.GetIntSetting(KIapTableIapNetworkDes, info().iNetId); + } + + ESock::XConnectionQuerySet* querySet = NULL; + if ( ret == KErrNone ) + { + TRAP(ret, querySet = ESock::XConnectionQuerySet::NewL() ); + } + + if ( ret == KErrNone ) + { + TRAP(ret, ESock::XUintQuery::NewL(KIapTableIdFieldId, *querySet) ); + } + + if ( ret == KErrNone ) + { + TRAP(ret, ESock::XUintQuery::NewL(KTapTableIapNetworkId, *querySet) ); + } + + ESock::CConnectionQuerySet* connectionQuerySet = NULL; + if ( ret == KErrNone ) + { + TRAP(ret, connectionQuerySet = ESock::CConnectionQuerySet::NewL(querySet) ); + } + + if ( ret == KErrNone ) + { + querySet = NULL; + } + + if ( ret == KErrNone ) + { + ret = conn.GetParameters( *connectionQuerySet ); + } + + if ( ret == KErrNone ) + { + TBool match = EFalse; + ESock::XConnectionQuerySet& outputQuerySet = connectionQuerySet->DataObject(); + ESock::XUintQuery* iapTableIdQuery = static_cast(outputQuerySet.FindQuery( KIapTableIdFieldId )); + ESock::XUintQuery* iapTableNetworkQuery = static_cast(outputQuerySet.FindQuery( KTapTableIapNetworkId )); + + match = ( iapTableIdQuery + && iapTableNetworkQuery + && iapTableIdQuery->Error() == KErrNone + && iapTableNetworkQuery->Error() == KErrNone + && iapTableIdQuery->IsQueryAnswered() + && iapTableNetworkQuery->IsQueryAnswered() + && iapTableIdQuery->Data() == info().iIapId + && iapTableNetworkQuery->Data() == info().iNetId + ); + + if ( !match ) + { + ret = KErrGeneral; + } + } + + delete querySet; + delete connectionQuerySet; + + REComSession::FinalClose(); + return ret; +} + +TInt TE_RConnectionStep::OpenUdpSocketL(RSocket& sock, RSocketServ& ss) +/** + * Open a UDP socket within the supplied socket server. No connection is + * specified so let the system implicitly decide which to use + * @param sock - the socket to open + * @param ss - the socket server + * @return system wide error code + */ +{ + TInt err = KErrNone; + TInt ret = KErrNone; + + INFO_PRINTF1(_L("Opening Implicit UDP Socket")); + + err = sock.Open(ss, KAfInet, KSockDatagram, KProtocolInetUdp); + TESTEL(KErrNone == ret, ret); + if (err != KErrNone) + ret = err; + + err = sock.SetOpt(KSoReuseAddr, KSolInetIp, 1); + TESTEL(err == KErrNone, err); + if (err != KErrNone) + ret = err; + + err = sock.SetLocalPort(iEchoPortNum); + TESTEL(err == KErrNone, err); + if (err != KErrNone) + ret = err; + + return ret; +} + +TInt TE_RConnectionStep::OpenUdpSocketExplicitL(RSocket& sock, RSocketServ& ss, RConnection& conn) +/** + * Open a UDP socket with the supplied socket server. Associate it + * with the specified connection. + * @param sock - the socket to open + * @param ss - the socket server + * @param conn - the connection to associate it with + * @return system wide error code + */ +{ + TInt err; + TInt ret = KErrNone; + INFO_PRINTF1(_L("Opening Explicit UDP Socket")); + + err = sock.Open(ss, KAfInet, KSockDatagram, KProtocolInetUdp, conn); + TESTEL(KErrNone == err, err); + if (err != KErrNone) + ret = err; + + err = sock.SetOpt(KSoReuseAddr, KSolInetIp, 1); + TESTEL(err == KErrNone, err); + if (err != KErrNone) + ret = err; + + err = sock.SetLocalPort(iEchoPortNum); + TESTEL(err == KErrNone, err); + if (err != KErrNone) + ret = err; + + return ret; +} + +void TE_RConnectionStep::DestroyUdpSocket(RSocket& sock) +/** + * Destroys the supplied socket + * @param sock - the socket to destroy + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Closing Socket")); + sock.Close(); +} + +TInt TE_RConnectionStep::OpenTcpSocket(RSocket& sock, RSocketServ& ss) +/** + * Open a TCP socket within the supplied socket server. No connection is + * specified so let the system implicitly decide which to use + * @param sock - the socket to open + * @param ss - the socket server + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Opening Implicit TCP Socket")); + return (sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp)); +} + +TInt TE_RConnectionStep::OpenTcpSocketExplicit(RSocket& sock, RSocketServ& ss, RConnection& conn) +/** + * Open a TCP socket within the supplied socket server. Associate it with + * the specified connection. + * @param sock - the socket to open + * @param ss - the socket server + * @param conn - the connection to associate it with + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Opening Explicit TCP Socket")); + return (sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, conn)); +} + +TInt TE_RConnectionStep::ConnectTcpSocket(RSocket& sock, TSockAddr& addr) +/** + * Connect the supplied TCP socket to the destination socket + * @param sock - the socket to connect up + * @param addr - the address of the destination to connect up to + */ +{ + TRequestStatus status; + INFO_PRINTF1(_L("Connecting TCP Socket")); + sock.Connect(addr, status); + User::WaitForRequest(status); + return status.Int(); +} + +TInt TE_RConnectionStep::ConnectFourTcpSockets(RSocket& sock1, RSocket& sock2, RSocket& sock3, RSocket& sock4, TSockAddr& dest) +/** + * Connect the supplied TCP sockets to the destination socket + * @param sock1 - the first of the sockets to connect up + * @param sock2 - the second of the sockets to connect up + * @param sock3 - the third of the sockets to connect up + * @param sock4 - the fourth of the sockets to connect up + * @param dest - the address of the destination to connect up to + */ +{ + TRequestStatus status[4]; + INFO_PRINTF1(_L("Connecting TCP Socket")); + sock1.Connect(dest, status[0]); + INFO_PRINTF1(_L("Connecting TCP Socket")); + sock2.Connect(dest, status[1]); + INFO_PRINTF1(_L("Connecting TCP Socket")); + sock3.Connect(dest, status[2]); + INFO_PRINTF1(_L("Connecting TCP Socket")); + sock4.Connect(dest, status[3]); + + // To avoid stray events we need (a) four signals and (b) all four sockets to have completed - as always it doesn't matter if the + // four signals aren't actually from these sockets, eg if lower priority things are completing + TInt signalsOutstanding = 4; + TBool allConnected; + do + { + User::WaitForAnyRequest(); + --signalsOutstanding; + allConnected = (status[0].Int() != KRequestPending) && (status[1].Int() != KRequestPending) && + (status[2].Int() != KRequestPending) && (status[3].Int() != KRequestPending); + } while(signalsOutstanding > 0 || !allConnected); + + // If other requests complete while we're waiting for ours then have to re-add their signals + while(signalsOutstanding < 0) + { + TRequestStatus status; + TRequestStatus* dummyStatus = &status; + User::RequestComplete(dummyStatus, KErrNone); + ++signalsOutstanding; + } + + if (status[0].Int() != KErrNone) + return status[0].Int(); + if (status[1].Int() != KErrNone) + return status[1].Int(); + if (status[2].Int() != KErrNone) + return status[2].Int(); + if (status[3].Int() != KErrNone) + return status[3].Int(); + + return KErrNone; +} + +TInt TE_RConnectionStep::DestroyTcpSocket(RSocket& sock) +/** + * Destroys the supplied socket + * @param sock - the socket to destroy + * @return system wide error code + */ +{ + TRequestStatus status; + INFO_PRINTF1(_L("Shutting down TCP Socket")); + sock.Shutdown(RSocket::EImmediate, status); + User::WaitForRequest(status); + sock.Close(); + + return status.Int(); +} + +TInt TE_RConnectionStep::OpenNullSocket(RSocket& sock, RSocketServ& ss) +/** + * Open a socket but not associated to any protocol + * @param sock - the socket to open + * @param ss - the socket server to use + * @return system wide error code + */ +{ + INFO_PRINTF1(_L("Open Null Socket")); + return (sock.Open(ss)); +} + +TInt TE_RConnectionStep::TransferSocket(RSocket& source, RSocket& target, RSocketServ& ss) +/** + * Transfer a socket to another socket + * @param source - the socket to transfer from + * @param target - the socket to transfer to + * @param ss - the socket server the original socket is in + * @return system wide error code + */ +{ + //-- note that RSocket::Transfer() operation since 8.1b shall be additionally enabled by + //-- setting KSOEnableTransfer socket option with appropriate capabilities set for the + //-- process that "pulls" the socket. It shall be done before calling this function. + TName name; + + source.Name(name); + + return target.Transfer(ss, name); +} + + +TInt TE_RConnectionStep::OpenHostResolver(RHostResolver& hr, RSocketServ& ss) +/** + * Open a host resolver within the supplied socket server. No connection is + * specified sp let the system decide which to use + * @param hr - the host resolver to open + * @param ss - the socket server to use + * @return system wide error code + */ +{ + return (hr.Open(ss, KAfInet, KProtocolInetTcp)); +} + +TInt TE_RConnectionStep::OpenHostResolverExplicit(RHostResolver& hr, RSocketServ& ss, RConnection& conn) +/** + * Open a host resolver within the supplied socket server. Associate it with + * the specified connection + * @param hr - the host resolver to open + * @param ss - the socket server to use + * @param conn - the connection to associate it with + * @return system wide error code + */ +{ + return (hr.Open(ss, KAfInet, KProtocolInetUdp, conn)); +} + +TInt TE_RConnectionStep::MakeNameRequest(RHostResolver& hr, const TDesC& aName) +/** + * Make a name request + * @param hr - the host resolver to make the request with + * @param aName - the name to resolve + * @return system wide error code + */ +{ + TRequestStatus status; + TNameEntry result; + INFO_PRINTF1(_L("Performing Asynchronous GetByName()")); + hr.GetByName(aName, result, status); + User::WaitForRequest(status); + + return status.Int(); +} + +TInt TE_RConnectionStep::MakeSynchronousNameRequest(RHostResolver& hr, const TDesC& aName) +/** + * Make a name request using the synchronous method + * @param hr - the host resolver to make the request with + * @param aName - the name to resolve + * @return system wide error code + */ +{ + TNameEntry result; + INFO_PRINTF1(_L("Performing Synchronous GetByName()")); + return (hr.GetByName(aName, result)); +} + +TInt TE_RConnectionStep::MakeAddressRequest(RHostResolver& hr, const TSockAddr& addr) +/** + * Make a request FOR a name using GetByAddress() + * @param hr - the host resolver to use + * @param addr - the address to pass in + * @return system wide error code + */ +{ + TRequestStatus status; + TNameEntry name; + INFO_PRINTF1(_L("Performing Asynchronous GetByAddress()")); + hr.GetByAddress(addr, name, status); + User::WaitForRequest(status); + + return status.Int(); +} + +TInt TE_RConnectionStep::MakeSynchronousAddressRequest(RHostResolver& hr, const TSockAddr& addr) +/** + * Make a request FOR a name using GetByAddress() [use the synchronous version] + * @param hr - the host resolver to use + * @param addr - the address to pass in + * @return system wide error code + */ +{ + TNameEntry name; + INFO_PRINTF1(_L("Performing Synchronous GetByAddress()")); + return (hr.GetByAddress(addr, name)); +} + +void TE_RConnectionStep::DestroyHostResolver(RHostResolver& hr) +/** + * Destroy the supplied host resolver + * @param hr - the host resolver to destroy + * @return system wide error code + */ +{ + hr.Close(); +} + +TInt TE_RConnectionStep::SendUdpData(RSocket& aSock, TSockAddr& aDest, TUint aPayloadSize) +/** + * Send UDP data (an ICMP packet) over the socket specified to the address specified. + * @param aSock The socket to use for the send + * @param aDest The destination to send the data to + * @param aPayloadSize The size of the packet to send + * @return system wide error code + */ +{ + TBuf8 buffer; + TRequestStatus status; + + // construct an ICMP packet to send on the socket + buffer.SetMax(); + buffer.FillZ(); + buffer[0] = (TUint8) 0x08; // ICMP type = 8 + buffer[1] = (TUint8) 0x00; // ICMP code = 0 + buffer[2] = (TUint8) 0xF7; // ICMP checksum high byte + buffer[3] = (TUint8) 0xFF; // ICMP checksum low byte + buffer[13] = (TUint8) 0xFE; + // NB the rest of the buffer is zero + // hence the checksum (0xFFFF - 0x800) since 0x8 + // is the only non-zero element of the buffer + + // set the length of the data to be sent to that specified (payload size!) + buffer.SetLength(aPayloadSize); + + // send the data out over the socket + aSock.SendTo(buffer, aDest, 0, status); + User::WaitForRequest(status); + + return status.Int(); +} + +TInt TE_RConnectionStep::RecvUdpData(RSocket& aSock, TSockAddr& aDest, TUint aPayloadSize) +/** + * Receive UDP packet from the network + * @param aSock The socket to receive the packet on + * @param aDest The address to receive the packet from + * @param aPayloadSize The size of the packet to receive + * @return system wide error code + */ +{ + TBuf8 buffer; + TRequestStatus status; + TInt timeoutInSecs = 10; + RTimer timer; + TRequestStatus timerStatus; + + // Create a timer so that we dont rely on being errored by esock alone + TInt ret; + if ((ret = timer.CreateLocal()) != KErrNone) + { + INFO_PRINTF2(_L("RTimer::CreateLocal() returned %d"), ret); + timer.Close(); // from looking at impl shouldn't do any harm to call Close() here + return ret; + } + + timer.After(timerStatus, timeoutInSecs * 1000000); + + buffer.Zero(); + buffer.SetLength(aPayloadSize); + + aSock.RecvFrom(buffer, aDest, 0, status); + User::WaitForRequest(status, timerStatus); + + // Timer expired, cancel the read + if(timerStatus != KRequestPending) + { + aSock.CancelAll(); + User::WaitForRequest(status); + timer.Close(); + return KErrTimedOut; + } + // otherwise cancel the timer + timer.Cancel(); + User::WaitForRequest(timerStatus); + timer.Close(); + + // don't use TESTEL here as the test case may be expecting us to fail and that's ok... + if (status != KErrNone) + return status.Int(); + else + { // check that what we sent is what we got back + // if the receive times out and we access buffer we get a panic + TEST(buffer[0] == 0x08); + TEST(buffer[1] == 0x00); + TEST(buffer[2] == 0xF7); + TEST(buffer[3] == 0xFF); + } + + return KErrNone; +} + +TInt TE_RConnectionStep::TestUdpDataPathL(RSocket& aSock, TSockAddr& aDest, TUint aPayloadSize) +/** + * Sends data to the address specified (dest) and expects to receive it looped back unchanged + * @param aSock The socket to send the data over (and receive it over) + * @param aDest The destination to send the traffic to + * @param aPayloadSize The amount of data to sent (defaults to KBufferLength) + * @return system wide error code + */ +{ + TInt err; + INFO_PRINTF1(_L("Sending UDP Data")); + err = SendUdpData(aSock, aDest, aPayloadSize); + if (err != KErrNone) + return err; + + INFO_PRINTF1(_L("Receiving UDP Data")); + err = RecvUdpData(aSock, aDest, aPayloadSize); + // don't use TESTEL here as the test case may be expecting us to fail and that's ok... + return err; +} + +TInt TE_RConnectionStep::SendTcpData(RSocket& aSock) +/** + * Send TCP data over the socket specified to the address specified. + * @param aSock The socket to use for the send + * @param aPayloadSize The size of the packet to send + * @return system wide error code + */ +{ + TRequestStatus status; + TBuf8 buffer; + + // build some data to send + buffer.SetMax(); + buffer.FillZ(); + buffer[0] = (TUint8) 0x08; // ICMP type = 8; + buffer[1] = (TUint8) 0x00; // ICMP code = 0; + buffer[2] = (TUint8) 0xF7; // ICMP checksum high byte + buffer[3] = (TUint8) 0xFF; // ICMP checksum low byte + + // send the data + aSock.Send(buffer, 0, status); + User::WaitForRequest(status); + + return status.Int(); +} + +TInt TE_RConnectionStep::RecvTcpData(RSocket& aSock) +/** + * Receive TCP packet from the network + * @param aSock The socket to receive the packet on + * @param aPayloadSize The size of the packet to receive + * @return system wide error code + */ +{ + TRequestStatus status; + TBuf8 buffer; + buffer.Zero(); + + // hopefully get the same data back that was sent + aSock.Recv(buffer, 0, status); + User::WaitForRequest(status); + + if (status != KErrNone) + return status.Int(); + else + { // check that what we sent is what we got back + // if the receive times out and we access the buffer we get a panic + TEST(buffer[0] == 0x08); + TEST(buffer[1] == 0x00); + TEST(buffer[2] == 0xF7); + TEST(buffer[3] == 0xFF); + } + + return KErrNone; +} + +TInt TE_RConnectionStep::TestTcpDataPathL(RSocket& sock) +/** + * Sends data and expects to receive it looped back unchanged + * @param sock The socket to send the data over (and receive it over) + * @param aPayloadSize The amount of data to sent (defaults to KBufferLength) + * @return system wide error code + * @note there is no address parameter, the socket must already be connected + */ +{ + TInt err; + + err = SendTcpData(sock); + if (err != KErrNone) + return err; + + err = RecvTcpData(sock); + + return err; +} + +TInt TE_RConnectionStep::NumberOfInterfacesL(RSocketServ& ss) +/** + * Return a count of interfaces in this socket server. + * Can be used even if this socket server has no open connections (because it + * temporarily opens one!). + * @param ss - the interesting socket server to count in + * @return number of interfaces, or it might leave + */ +{ + TInt err; + RConnection conn; + TUint numOfConnections; + + err = OpenConnection(conn, ss); + TESTEL(KErrNone == err, err); + CleanupClosePushL(conn); + + err = EnumerateConnections(conn, numOfConnections); + TESTEL(KErrNone == err, err); + + CloseConnection(conn); + CleanupStack::Pop(); + + return numOfConnections; +} + +TInt TE_RConnectionStep::TimeUntilRequestComplete(TRequestStatus& status, TTimeIntervalSeconds& timeElapsed) +/** + * Wait for the status to change. Count how long it takes. + * @param status - the status which we need to wait for it to change + * @param timeElapsed - the time it took (in seconds) + * @return system wide error code + */ +{ + TTime time1, time2; + + time1.HomeTime(); + + User::WaitForRequest(status); + + time2.HomeTime(); + time2.SecondsFrom(time1, timeElapsed); + + return (status.Int()); +} + +TInt TE_RConnectionStep::RequestInterfaceDownL(RConnection& conn, RSocketServ& ss) +/** + * Sends a special packet to the dummy nif telling it to signal that the interface is down + * @param conn The connection to signal + * @param ss The socket server that the connection is within + * @return system wide error code + */ +{ + TInt err = KErrNone; + TRequestStatus status; + + TBuf8 buffer; + + RSocket sock; + TInetAddr dest; + + err = OpenUdpSocketExplicitL(sock, ss, conn); + TESTEL(KErrNone == err, err); + CleanupClosePushL(sock); + + //err = sock.SetLocalPort(KDummyNifCmdPort); + //TESTEL(KErrNone == err, err); + + dest.SetAddress(KDummyNifLocalAddressBase + 4); + dest.SetPort(KDummyNifCmdPort); + + buffer.SetMax(); + buffer.FillZ(); + buffer[0] = (TUint8) KForceDisconnect; + + sock.SendTo(buffer, dest, 0, status); + User::WaitForRequest(status); + TESTEL(KErrNone == status.Int(), status.Int()); + + buffer.Zero(); + // I expect some sort of response + // this fails - possibly ok as the interface might have gone already?? + //sock.RecvFrom(buffer, dest, 0, status); + //User::WaitForRequest(status); + //TESTEL(KErrNone == status.Int(), status.Int()); + + DestroyUdpSocket(sock); + CleanupStack::Pop(); + + return err; +} + +TInt TE_RConnectionStep::RequestSetStausL(RConnection& conn, RSocketServ& ss, TSubConnectionUniqueId aSubConnId) +/** + * Sends a special packet to the dummy nif allowing the setting of the connection progress + * @param conn The connection to signal + * @param ss The socket server that the connection is within + * @return system wide error code + */ +{ + TInt err = KErrNone; + TRequestStatus status; + + TBuf8 buffer; + + RSocket sock; + TInetAddr dest; + + err = OpenUdpSocketExplicitL(sock, ss, conn); + TESTEL(KErrNone == err, err); + CleanupClosePushL(sock); + + dest.SetAddress(KDummyNifLocalAddressBase + 4); + dest.SetPort(KDummyNifCmdPort); + + buffer.SetMax(); + buffer.FillZ(); + buffer[0] = (TUint8) KForceFinishedSelection; + buffer[1] = (TUint8) aSubConnId; + + sock.SendTo(buffer, dest, 0, status); + User::WaitForRequest(status); + TESTEL(KErrNone == status.Int(), status.Int()); + + buffer.Zero(); + + DestroyUdpSocket(sock); + CleanupStack::Pop(); + + return err; +} + + +TInt TE_RConnectionStep::WaitForAllInterfacesToCloseL(RSocketServ& ss, TTimeIntervalSeconds aMaxSecsToWait) +/* + * Sit around waiting for all the interfaces to die (essentially poll every now + * and again until there are zero interfaces in this socket server left) + * @param ss Socket Server session to use + * @param aMaxSecsToWait maximum number of seconds to wait for the interface to come down. + * @return system wide error code + */ + { + TInt err; + TUint numOfConnections; + TInt count = 0; + const TInt KOneSecond = 1000000; + + RConnection conn; + + err = OpenConnection(conn, ss); + TESTEL(KErrNone == err, err); + CleanupClosePushL(conn); + + err = EnumerateConnections(conn, numOfConnections); + TESTEL(KErrNone == err, err); + + while ((0 != numOfConnections) && (count < aMaxSecsToWait.Int())) + { + count++; + User::After(KOneSecond); // wait a bit, a second sounds good + err = EnumerateConnections(conn, numOfConnections); + } + + CloseConnection(conn); + CleanupStack::Pop(); + + if (numOfConnections != 0) + { + return KErrTimedOut; + } + + return KErrNone; + } + +void TE_RConnectionStep::PerformDummyStartAttachOperationsL(RSocketServ& ss, TPckgBuf& info) +/* + * Do some attached and starts. One monitor, one normal and one actual interface. + * Close in two different orders. + * @param ss - the socket server to do this in + * @param info - some info + * @return system wide error code + */ +{ + TInt err; + + RConnection conn1, conn2, conn3; + + TInt count; + + for (count=0; count<2; count++) + { + // attach one as a monitor + err = OpenConnection(conn1, ss); + TESTEL(KErrNone == err, err); + CleanupClosePushL(conn1); + err = AttachMonitor(conn1, info); + TESTEL(KErrNone == err, err); + + // attach one normally + err = OpenConnection(conn2, ss); + TESTEL(KErrNone == err, err); + CleanupClosePushL(conn2); + err = AttachNormal(conn2, info); + TESTEL(KErrNone == err, err); + + // create an actual interface (maybe?) + err = OpenConnection(conn3, ss); + TESTEL(KErrNone == err, err); + CleanupClosePushL(conn3); + err = StartConnectionWithOverrides(conn3, iDummyNifIap); + TESTEL(KErrNone == err, err); + + if (count == 0) + { + // On first time thru close the interfaces in reverse order + CloseConnection(conn3); + CleanupStack::Pop(); + CloseConnection(conn2); + CleanupStack::Pop(); + CloseConnection(conn1); + CleanupStack::Pop(); + } + else + { + // Second time thru close in a different order (fwd order) + CloseConnection(conn1); + CleanupStack::Pop(3); + CleanupClosePushL(conn3); // sneaky.... put them back on in the + CleanupClosePushL(conn2); // order that is easier for us below... + CloseConnection(conn2); + CleanupStack::Pop(); + CloseConnection(conn3); + CleanupStack::Pop(); + } + } +} + +void TE_RConnectionStep::AllInterfaceNotification(RConnection& conn, TRequestStatus& status, TDes8& aNotification) +/** + * Requests all interface notification + * @param conn The connection to use to request notification + * @param status Asynchronous status of the request + * @param aNotification The descriptor which the notification is to be written into + * @return nothing + */ + { + conn.AllInterfaceNotification(aNotification, status); + } + +void TE_RConnectionStep::CancelAllInterfaceNotificationL(RConnection& conn) +/** + * Cancels outstanding request for all interface notification + * @param conn The connection on which to cancel the request + * @return nothing + */ + { + conn.CancelAllInterfaceNotification(); + } + +void TE_RConnectionStep::CheckInterfaceNotificationL(TRequestStatus& status, TInterfaceNotificationBuf& info, TConnInterfaceState interfaceState, RConnection* sourceConnection) +/** + * Checks for particular connection interface state + * @param status Asynchronous status of request + * @param info Buffer which info will be written into + * @param interfaceState Also will be updated and then monitored + * @param sourceConnection Connection which all this relates to + * @return nothing + */ + // checks for particular connection interface state + { + // wait for completion - to ensure that monitoring actually occurs + User::WaitForRequest(status); + + // check request completed OK + TESTEL(status.Int() == KErrNone, status.Int()); + + // check connection state is as expected + TESTEL(info().iState == interfaceState, info().iState); + + if(NULL != sourceConnection) + { + CheckConnectionInfoL(*sourceConnection,info().iConnectionInfo); + } + } + +void TE_RConnectionStep::CheckConnectionInfoL(RConnection& connection, TConnectionInfo& info) +/** + * Checks connection info with the expected + * @param connection The connection all this relates to + * @param info The info to compare with the actual settings for connection + * @return nothing + */ + { + TInt err; + TUint32 connIapId; + TUint32 connNetId; + + // get settings for the connection + err = connection.GetIntSetting(_L("IAP\\Id"), connIapId); + TESTEL(err == KErrNone, err); + err = connection.GetIntSetting(_L("IAP\\IAPNetwork"), connNetId); + TESTEL(err == KErrNone, err); + + // check IAP Id matches + TESTEL(info.iIapId == connIapId, info.iIapId); + // check Network Id matches + TESTEL(info.iNetId == connNetId, info.iNetId); + } + +TInt TE_RConnectionStep::EnumerateClients(RConnection& aConn, TUint aIndex, TUint& aCount) +/* + * Count how many clients there are + * @param aConn The connection to use to enumerate the clients + * @param aIndex The index to use + * @param aCount The count of how many clients there are + * @return system wide error code + */ + { + + TInt err(KErrNone); + + TConnEnumArgBuf args; + args().iIndex = aIndex; + err = aConn.Control(KCOLConnection, KCoEnumerateConnectionClients, args); + aCount = args().iCount; + + return err; + } + +TInt TE_RConnectionStep::GetConnectionClientInfo(RConnection& aConn, TUint aIndex, TConnectionClientInfo& aClientInfo) +/** + * Get the information about a client + * @param aConn The connection to use + * @param aIndex The index to use + * @param aClientInfo Where to write the information to + * @return system wide error code + */ + { + + TInt err(KErrNone); + + TConnGetClientInfoArgBuf args; + args().iIndex = aIndex; + err = aConn.Control(KCOLConnection, KCoGetConnectionClientInfo, args); + aClientInfo = args().iClientInfo; + + return err; + } + +TInt TE_RConnectionStep::EnumerateSockets(RConnection& aConn, TUint aIndex, TUint& aCount) +/** + * Count how many sockets there are + * @param aConn The connection to use + * @param aIndex The index to use + * @param aCount The count of how many sockets there are + * @return system wide error code + */ + { + + TInt err(KErrNone); + + TConnEnumArgBuf args; + args().iIndex = aIndex; + err = aConn.Control(KCOLConnection, KCoEnumerateConnectionSockets, args); + aCount = args().iCount; + + return err; + } + +TInt TE_RConnectionStep::GetConnectionSocketInfo(RConnection& aConn, TUint aIndex, TConnectionSocketInfo& aSocketInfo) +/** + * Get the information about a socket + * @param aConn The connection to use + * @param aIndex The index to use + * @param aSocketInfo Where to write the information to + * @return system wide error code + */ + { + + TInt err(KErrNone); + + TConnGetSocketInfoArgBuf args; + args().iIndex = aIndex; + err = aConn.Control(KCOLConnection, KCoGetConnectionSocketInfo, args); + aSocketInfo = args().iSocketInfo; + + return err; + } + +TInt TE_RConnectionStep::LoadNapt(RSocket& aNaptsock,RSocket& aTestServSock, RSocketServ& aSockServer) +/** + * Load Napt.Provide TInterfaceLockInfo information + * @param naptsock - the napt socket to open + * @param ss - the socket server + * @param testServSock - socket connected to test server + * @return system wide error code + */ + { + const TInt netMaskLength = 8; + TInt err(KErrNone); + + err = aNaptsock.Open(aSockServer,_L("napt")); + if(err != KErrNone) + { + INFO_PRINTF2(_L("Load NAPT failed with error: %d."),err); + return err; + } + + _LIT(KInterfaceName,"ipcp::comm"); + _LIT(KInterfaceName1,"eth"); + TUint32 testaddr = GetInterfaceAddress(aTestServSock,KInterfaceName()); + + TPckgBuf info; + info().iPublicIap = iNaptPublicIap; + info().iPrivateIap = iNaptPrivateIap; + TInetAddr::Cast (info().iPrivateIp).SetV4MappedAddress(iNaptTestServAddr.Address()); + TInetAddr::Cast(info().iPublicIp).SetV4MappedAddress(testaddr) ; + info().iNetmaskLength = netMaskLength; + info().iIfIndex = GetInterfaceIndexL(aTestServSock, KInterfaceName1()); +#ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION + info().iUplinkAccess = ETrue; +#endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION + + err = aNaptsock.SetOpt(KSoNaptSetup,KSolNapt,info); + if(err != KErrNone) + { + INFO_PRINTF2(_L("Set Option for NAPT failed with error: %d."),err); + return err; + } + return err; + } + +TInt TE_RConnectionStep::ProdQoSL(RConnection& aConn, RSocketServ& aSs) +/** + * If you want to use the primary context on a NIF, GUQoS will drop the first packet you send (as it won't yet be aware of the primary). So call this method which sends a packet (thus prodding GUQoS into life). + * @param aConn A connection to send the packet over (should really be an interface supporting multiple contexts!) + * @param aSs A socket server within which the connection was created + * @return system wide error code + */ +{ + TInt err; + RSocket sock; + + err = OpenUdpSocketExplicitL(sock, aSs, aConn); + TESTEL(KErrNone == err, err); + + err = SendUdpData(sock, iEchoServerAddr, KSmallBufferLength); + TESTEL(KErrNone == err, err); + CleanupClosePushL(sock); + + DestroyUdpSocket(sock); + CleanupStack::Pop(&sock); + + User::After(KOneSecondDelay); + + return err; // will always be KErrNone if we reach here +} + +/** + * Waits idefinitely until a relevant (specified) progress notification is received. + * All other progress notifications are ignored. + * On return, aProgress contains the requested progress. + * @param aConn A connection to wait on for a progress. + * @param aStatus progress notification request status. + * @param aProgress a buffer for the relevant progress. + * @param aRelevantProgress a progress to wait for. + */ +void TE_RConnectionStep::WaitForRelevantProgress(RConnection& aConn, TNifProgressBuf& aProgress, TInt aRelevantProgress) + { + TRequestStatus reqStatus; + + for(;;) // WINS compiler generates a warning if while(ETrue) is used. + { + aConn.ProgressNotification(aProgress, reqStatus); + User::WaitForRequest(reqStatus); + if(aRelevantProgress == aProgress().iStage) + { + break; + } + } + } + +TUint32 TE_RConnectionStep::GetInterfaceAddress(RSocket& sock,const TDesC& aFName) +/** + * Get interface gloabal Ip Address + * @param sock - socket connection + * @param aFName - interface name + * @return Ip address + */ +{ + TName address; + TBool isSiteLocal,isLinkLocal; + TInt retVal = -1; + + TPckgBuf info; + + retVal = sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl); + TESTEL(retVal == KErrNone, retVal); + + retVal = sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); + TESTEL(retVal == KErrNone, retVal); + + while(retVal==KErrNone) + { + info().iAddress.Output(address); + + isSiteLocal = info().iAddress.IsSiteLocal(); + isLinkLocal = info().iAddress.IsLinkLocal(); + + TInt str = info().iName.Find(aFName); + if((str == KErrNone) && (isSiteLocal == EFalse) && (isLinkLocal == EFalse)) + { + INFO_PRINTF2(_L("Interface address obtained: %S."),&address); + break; + } + + retVal = sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); + } + + return info().iAddress.Address(); +} + +TUint32 TE_RConnectionStep::GetInterfaceIndexL(RSocket& sock,const TDesC& aFName) +/** + * Get interface index + * @param sock - socket connection + * @param aFName - interface name + * @return Interface index + */ +{ + TPckgBuf interfaceInfo; + TPckgBuf queryInfo; + + TName address; + TInt retVal = KErrNotFound; + + retVal = sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl); + TESTEL(retVal == KErrNone, retVal); + + retVal = sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, interfaceInfo); + TESTEL(retVal == KErrNone, retVal); + + while(retVal==KErrNone) + { + TInt str = interfaceInfo().iName.Find(aFName); + if(str == KErrNone) + { + queryInfo().iName = interfaceInfo().iName; + break; + } + retVal = sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, interfaceInfo); + } + TESTEL(retVal == KErrNone, retVal); + + retVal = sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, queryInfo); + TESTEL(retVal == KErrNone, retVal); + + return queryInfo().iIndex; +} + + + +/* + * Now the stuff for the peculiar tests that need to use QoS + */ + +TE_RConnectionQoSStep::TE_RConnectionQoSStep() : TE_RConnectionStep() +/** + * Constructor for TE_RConnectionQoSStep, an abstract class derived from by any steps dealing with QoS. Must use two phase construction. + */ +{ +} + +void TE_RConnectionQoSStep::Log( TRefByValue format, ... ) + { + VA_LIST aList; + VA_START( aList, format ); + + // decode formated data for display on console + TBuf LineBuf; + LineBuf.AppendFormatList( format, aList ); + + INFO_PRINTF1(LineBuf); + + VA_END( aList ); + } + + + + + +TE_RConnectionQoSStep::TS_QosChannel::TS_QosChannel(TE_RConnectionQoSStep& aTestStep) +:iTestStep(aTestStep) +/** + * Constructor for TE_RConnectionQoSStep, an abstract class derived from by any steps dealing with QoS. Must use two phase construction. + */ +{ +} + + +TE_RConnectionQoSStep::TS_QosChannel::~TS_QosChannel() +/** + * Destructor for ~TS_QosChannel + */ +{ +} + +void TE_RConnectionQoSStep::TS_QosChannel::ConstructL() +/** + * Second phase constructor for TE_RConnectionQoSStep derived classes. + * @param none + * @return nothing + */ +{ +} + + +TInt TE_RConnectionQoSStep::TS_QosChannel::Open(RSocketServ& aServer, RConnection& aConnection) +{ + return iChannel.Open(aServer, RSubConnection::ECreateNew, aConnection); +} + + +TInt TE_RConnectionQoSStep::TS_QosChannel::Add(RSocket aSocket) +{ + TRequestStatus subconnReqStat; + iChannel.Add(aSocket, subconnReqStat); + User::WaitForRequest(subconnReqStat); + return subconnReqStat.Int(); +} + +TInt TE_RConnectionQoSStep::TS_QosChannel::Close() +{ + iChannel.Close(); + REComSession::FinalClose(); + return KErrNone; +} + +TInt TE_RConnectionQoSStep::TS_QosChannel::SetQoSParametersL() +/** + * Set up a standard set of QoS parameters to be used by derived classes + * @param aParameters Where to write the standard parameters to + * @return system wide error code + */ +{ + TInt err = KErrNone; + //------------------------------------ + //1. Initialise QoS params structure; + //------------------------------------ + //create a container for QoS sub connection parameters (Param bundle takes ownership) + RSubConParameterBundle subconnParams; + CleanupClosePushL(subconnParams); + + CSubConParameterFamily* family = CSubConParameterFamily::NewL(subconnParams, KSubConQoSFamily); + + //create the generic set + CSubConQosGenericParamSet* subConQosGenParSet = CSubConQosGenericParamSet::NewL(*family, CSubConParameterFamily::ERequested); + + //Qos mapping extracted from ipcpr.cpp MapGenericParamsFromESockToPRTL(...) + + //1. TokenRateUplink + //NO MAPPING for subConQosGenParSet->SetTokenRateUplink(1024); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetTokenRateUplink(TUint32 aRate); + + //2. TokenBucketSizeUplink + //Mapping based on: + // TInt uplinkBandwidth = generic->GetUplinkBandwidth(); + // params.SetTokenBucketSizeUplink((TUint32)uplinkBandwidth); + subConQosGenParSet->SetUplinkBandwidth(896); + + //3. MaxTransferRateUplink + //Mapping based on: + // TInt upLinkMaximumBurstSize = generic->GetUpLinkMaximumBurstSize(); + // params.SetMaxTransferRateUplink((TUint32)upLinkMaximumBurstSize); + subConQosGenParSet->SetUpLinkMaximumBurstSize(1024); + + //4. MaxPacketSizeUplink + //Mapping based on: + // TInt upLinkMaximumPacketSize = generic->GetUpLinkMaximumPacketSize(); + // params.SetMaxPacketSizeUplink((TUint32)upLinkMaximumPacketSize); + subConQosGenParSet->SetUpLinkMaximumPacketSize(735); + + //5. MinPolicedUnitUplink + //Mapping based on: + // TInt upLinkDelayVariation = generic->GetUpLinkDelayVariation(); + // params.SetMinPolicedUnitUplink((TUint32)upLinkDelayVariation); + subConQosGenParSet->SetUpLinkDelayVariation(0); + + //6. DelayUplink + //Mapping based on: + // TInt upLinkDelay = generic->GetUpLinkDelay(); + // params.SetDelayUplink((TUint32)upLinkDelay); + subConQosGenParSet->SetUpLinkDelay(0); + + //7. PriorityUplink + //Mapping based on: + // TInt upLinkPriority = generic->GetUpLinkPriority(); + // params.SetPriorityUplink((TUint16)upLinkPriority); + subConQosGenParSet->SetUpLinkPriority(3); + + //8. DropModeUplink + //NO MAPPING for subConQosGenParSet->SetDropModeUplink(KPfqosDropTail); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetDropModeUplink(TUint8 aDropMode); + + //9. TokenRateDownlink + //NO MAPPING for subConQosGenParSet->SetTokenRateDownlink(1024); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetTokenRateDownlink(TUint32 aRate); + + //10. TokenBucketSizeDownlink + //Mapping based on: + // TInt downlinkBandwidth = generic->GetDownlinkBandwidth(); + // params.SetTokenBucketSizeDownlink((TUint32)downlinkBandwidth); + subConQosGenParSet->SetDownlinkBandwidth(768); + + //11. MaxTransferRateDownlink + //Mapping based on: + // TInt downLinkMaximumBurstSize = generic->GetDownLinkMaximumBurstSize(); + // params.SetMaxTransferRateDownlink((TUint32)downLinkMaximumBurstSize); + subConQosGenParSet->SetDownLinkMaximumBurstSize(1024); + + //12. MaxPacketSizeDownlink + //Mapping based on: + // TInt downLinkMaximumPacketSize = generic->GetDownLinkMaximumPacketSize(); + // params.SetMaxPacketSizeDownlink((TUint32)downLinkMaximumPacketSize); + subConQosGenParSet->SetDownLinkMaximumPacketSize(512); + + //13. MinPolicedUnitDownlink + //Mapping based on: + // TInt downLinkDelayVariation = generic->GetDownLinkDelayVariation(); + // params.SetMinPolicedUnitDownlink((TUint32)downLinkDelayVariation); + subConQosGenParSet->SetDownLinkDelayVariation(300); + + //14. DelayDownlink + //Mapping based on: + // TInt downLinkDelay = generic->GetDownLinkDelay(); + // params.SetDelayDownlink((TUint32)downLinkDelay); + subConQosGenParSet->SetDownLinkDelay(200); + + //15. PriorityDownlink + //Mapping based on: + // TInt downLinkPriority = generic->GetDownLinkPriority(); + // params.SetPriorityDownlink((TUint16)downLinkPriority); + subConQosGenParSet->SetDownLinkPriority(128); + + //16. DropModeDownlink + //NO MAPPING for subConQosGenParSet->SetDropModeDownlink(KPfqosDropTail); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetDropModeDownlink(TUint8 aDropMode); + + //17. AdaptationPriority + //NO MAPPING for subConQosGenParSet->SetAdaptationPriority(KQoSLowestPriority); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetAdaptationPriority(TUint8 aPriority); + + //17. AdaptationPriority + //NO MAPPING for subConQosGenParSet->SetAdaptMode(EFalse); + //mapping commented out from MapGenericParamsFromESockToPRTL: + //params.SetAdaptMode(TBool aCanAdapt); + + //------------------------------------ + //2. Subscribe for QoS Params notification + //------------------------------------ + TNotificationEventBuf subconnNotifBuf; + TRequestStatus subconnReqStat; + RSubConnection::TEventFilter subconnEventFilter( + KSubConnGenericEventsImplUid, + KSubConGenericEventParamsGranted | + KSubConGenericEventParamsChanged | + KSubConGenericEventParamsRejected ); + iChannel.EventNotification(subconnNotifBuf, + &subconnEventFilter, 1, subconnReqStat); + + //------------------------------------ + //3. Set the QoS Parameters + //------------------------------------ + User::LeaveIfError(iChannel.SetParameters(subconnParams)); + + //------------------------------------ + //4. Receive & Process the event (expecting KSubConGenericEventParamsGranted) + //------------------------------------ + User::WaitForRequest(subconnReqStat); + User::LeaveIfError(subconnReqStat.Int()); + + + switch (subconnNotifBuf.Id()) + { + case KSubConGenericEventParamsGranted: + iTestStep.Log(_L("CSubConGenericEventParamsGranted received")); + break; + case KSubConGenericEventParamsChanged: + iTestStep.Log(_L("CSubConGenericEventParamsChanged received")); + break; + case KSubConGenericEventParamsRejected: + iTestStep.Log(_L("CSubConGenericEventParamsRejected received")); + err = KErrNotSupported; + break; + default: + iTestStep.Log(_L("unknown event received. Id=%d"),subconnNotifBuf.Id()); + err = KErrNotSupported; + break; + } + + subconnParams.Close(); + CleanupStack::Pop(&subconnParams); + + return err; +} + + +CStatus::CStatus():CActive(0) +{ + CActiveScheduler::Add(this); + SetActive(); +} + +CStatus::~CStatus() +{ + Cancel(); +} + +TInt TE_RConnectionSimTsyDataStep::NTRasThreadFunction(TAny* /*aThreadData*/) + { + _LIT(KCsyName,"LOOPBACK.CSY"); + _LIT(KPortName,"LOOPBACK::1"); + _LIT8(KServerText,"SERVER"); + + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (!cleanup) + { + return KErrNoMemory; + } + + RCommServ commServ; + TInt ret = commServ.Connect(); + if (KErrNone != ret) + { + return ret; + } + + ret = commServ.LoadCommModule(KCsyName); + if(KErrNone == ret) + { + RComm comm; + ret = comm.Open(commServ, KPortName, ECommShared); + if(KErrNone == ret) + { + TBuf8<6> readBuf; + TRequestStatus stat0; + comm.Read(stat0, readBuf); + User::WaitForRequest(stat0); + + comm.Write(stat0, KServerText); + User::WaitForRequest(stat0); + } + comm.Close(); + } + commServ.Close(); + delete cleanup; + return ret; + } + +TInt TE_RConnectionSimTsyDataStep::StartNTRasSimulation() + { + const TInt KStackSize=0x8000; + const TInt KHeapSize=0x8000; + const TInt KMaxHeapSize=0x80000; + TInt res = KErrNone ; + _LIT(KNtRasName,"NTRasEmulation"); + + RThread t; + res=t.Create(KNtRasName, NTRasThreadFunction, + KStackSize,KHeapSize,KMaxHeapSize,NULL); + t.Resume(); + t.Close(); + + return res; + } + +enum TVerdict TE_RConnectionSimTsyDataStep::doTestStepPreambleL() + { + _LIT(KPhbkSyncCMI, "phbsync.cmi"); + if (StartC32WithCMISuppressions(KPhbkSyncCMI) != KErrNone) + { + return EFail; + } + + // Wait for all of the interfaces to close down + RSocketServ ss; + User::LeaveIfError(ss.Connect()); + CleanupClosePushL(ss); + + if (KErrNone != WaitForAllInterfacesToCloseL(ss)) + { + INFO_PRINTF1(_L("Previous test case has left connections up that have not closed. Stopping them.")); + TBuf<200> errDesc; + TInt err; + if ((err = ESockTestUtils::StopAllInterfaces(errDesc)) != KErrNone) + { + INFO_PRINTF3(_L("StopAllInterfaces() err=%d\n%S"), err, &errDesc); + CleanupStack::PopAndDestroy(&ss); + return EFail; + } + } + CleanupStack::PopAndDestroy(&ss); + + TInt ret = RProperty::Set(KUidPSSimTsyCategory, KPSSimTsyTestNumber, 0); + if (ret != KErrNone) + { + INFO_PRINTF1(_L("Failed resetting")); + User::Leave(ret); + } + + ret = iTelServer.Connect(); + if (ret!=KErrNone) + { + INFO_PRINTF1(_L("Failed to connect to telephony server")); + User::Leave(ret); + } + + ret=iTelServer.LoadPhoneModule(KSimtsyName); + if (ret!=KErrNone) + { + INFO_PRINTF1(_L("Failed to load phone module")); + iTelServer.Close(); + User::Leave(ret); + } + + ret=iPhone.Open(iTelServer,KPhoneName) ; + if (ret!=KErrNone) + { + INFO_PRINTF1(_L("Failed to open phone module")); + iTelServer.UnloadPhoneModule(KSimtsyName); + iTelServer.Close(); + User::Leave(ret); + } + ret=iPhone.Initialise(); + if (ret!=KErrNone) + { + INFO_PRINTF1(_L("Failed to initialise the phone")); + iPhone.Close(); + iTelServer.UnloadPhoneModule(KSimtsyName); + iTelServer.Close(); + User::Leave(ret); + } + + RPhone::TCaps phoneCaps; + ret = iPhone.GetCaps(phoneCaps) ; + if ((KErrNone != ret) || !(phoneCaps.iFlags & RPhone::KCapsData)) + { + INFO_PRINTF2(_L("This phone does not support data calls (caps=0x%x)"), phoneCaps.iFlags); + iPhone.Close(); + iTelServer.UnloadPhoneModule(KSimtsyName); + iTelServer.Close(); + User::Leave(ret); + } + + return TestStepResult(); + } + +enum TVerdict TE_RConnectionSimTsyDataStep::doTestStepPostambleL() + { + REComSession::FinalClose(); + iPhone.Close(); + iTelServer.UnloadPhoneModule(KSimtsyName); + iTelServer.Close(); + + __UHEAP_MARKEND; + return TestStepResult(); + } +