telephonyprotocols/secondarypdpcontextumtsdriver/te_spudRSubConn/src/te_spudRSubConnSteps.cpp
// Copyright (c) 2005-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:
// te_spudNetworkSideSteps.cpp
// Implements the integration tests for the SPUD using RawIpNif
//
//
/**
@file
@internalComponent
*/
#include "te_spudRSubConnSteps.h"
#include <simtsy.h>
#include <commdbconnpref.h>
#include <nifvar.h> // Nifman Progress notifications
#include <es_enum.h>
#include <c32comm.h> // uniquely for the call to StartC32WithCMISuppressions
#include <e32property.h>
#include <ip_subconparams.h>
namespace
{
const TInt KMaxMsgLen = 128;
}
/**
Implements the pure virtual doTestStepPreambleL defined in CTestStep.
Used to disable the phone book synchronizer
which may cause the tests to fail.
@return EPass if successful.
@leave If Phonebook synchronizer disabling fails.
*/
TVerdict CSpudRSubConnTestStepBase::doTestStepPreambleL()
{
_LIT(KPhbkSyncCMI, "phbsync.cmi");
TInt err = StartC32WithCMISuppressions(KPhbkSyncCMI);
TESTL(KErrNone == err || KErrAlreadyExists == err);
INFO_PRINTF1(_L("Test Step Preamble: disabled Phonebook Synchronizer."));
return EPass;
}
/**
Implements the pure virtual doTestStepL defined in CTestStep.
Allows the base class to execute before any of the derived
tests is called.
@leave If any of the called methods leaves.
*/
TVerdict CSpudRSubConnTestStepBase::doTestStepL()
{
// Tell SIM.TSY which test it should load.
// If this is removed, SIM TSY will load test 0.
TInt simTsyTestNum = -1;
ASSERT(GetIntFromConfig(ConfigSection(), _L("SimTsyTestNum"), simTsyTestNum));
ASSERT(simTsyTestNum >= 0);
TInt ret0 = RProperty::Set(KUidPSSimTsyCategory,KPSSimTsyTestNumber,simTsyTestNum);
if (ret0 != KErrNone)
{
ret0 = RProperty::Set(KUidPSSimTsyCategory,KPSSimTsyTestNumber,simTsyTestNum);
}
TRAPD(esockConnErr, TestL(iESock.Connect(), _L("RSockeServ::Connect")));
if(KErrNone != esockConnErr)
{
INFO_PRINTF1(_L("ESock thread is dead. Most likely, it was crashed by the previous test case. Check the Root Server logs."));
SetTestStepResult(EInconclusive);
return TestStepResult();
}
ASSERT(!CActiveScheduler::Current()); // We should not have an AS at this point.
CActiveScheduler* testSched = new(ELeave) CActiveScheduler;
CleanupStack::PushL(testSched);
CActiveScheduler::Install(testSched);
// Test sequence itself:
TVerdict testResult = EFail;
TRAPD(err, testResult = RunTestStepL());
if(KErrNone == err)
{
INFO_PRINTF1(_L("Test Step Completion."));
SetTestStepResult(testResult);
}
else
{
ERR_PRINTF2(_L("Test Step Failure: the step left with [%d]"), err);
SetTestStepResult(EFail);
}
// It's ok to close everything more than once, or if not opened...
iPrimCtxSock1.Close();
iScndCtxSock1.Close();
iSpudScndCtx1.Close();
iSpud.Close(); // SPUD will linger, we don't care.
iESock.Close();
CActiveScheduler::Install(NULL); // uninstall the test scheduler
CleanupStack::PopAndDestroy(testSched);
return TestStepResult();
}
/**
Logs a message and leaves on error
@param aErrCode error code to check
@param aMsg message to log
@leave if aError is other than KErrNone
*/
void CSpudRSubConnTestStepBase::TestL(TInt aErrCode, const TDesC& aMsg)
{
TestL(aErrCode, KErrNone, aMsg);
}
/**
Used to verify that an error code is what expected, and log the associated comment
@param aErrCode the error code to check
@param aExpErrCode the expected error code
@param aMsg the message to log before testing
@leave if aErrCode != aExpErrCode
*/
void CSpudRSubConnTestStepBase::TestL(TInt aErrCode, TInt aExpErrCode, const TDesC& aMsg)
{
if(aExpErrCode == aErrCode)
{
INFO_PRINTF3(_L("%S: err[%d], as expected. OK."), &aMsg, aErrCode);
}
else
{
ERR_PRINTF5(_L("%S FAILED: err[%d], expected [%d]. Leaving with [%d])."), &aMsg, aErrCode, aExpErrCode, aErrCode);
User::Leave(aErrCode);
}
}
/**
Used to verify that a boolean is as expected, and log the associated comment
@param aBool the boolean to check
@param aMsg the message to log before testing
@leave if aBool == EFalse
*/
void CSpudRSubConnTestStepBase::TestBooleanTrueL(TBool aBool, const TDesC& aMsg)
{
if(aBool)
{
INFO_PRINTF2(_L("%S: Value is true, as expected. OK."), &aMsg);
}
else
{
ERR_PRINTF2(_L("Failed, %S: Value is false. Leaving with KErrGeneral)."), &aMsg);
User::Leave(KErrGeneral);
}
}
/**
Open and Start an interface */
void CSpudRSubConnTestStepBase::OpenAndStartInterfaceL(RConnection& aConn, TCommDbConnPref& aPref, TRequestStatus& aSt, const TDesC& aLogMsg)
{
INFO_PRINTF3(_L("%S: Opening and Starting RConnection on IAP=%d."), &aLogMsg, aPref.IapId());
TInt openErr = aConn.Open(iESock, KAfInet);
TestL(openErr, KErrNone, _L("Opening RConnection"));
aConn.Start(aPref, aSt);
}
void CSpudRSubConnTestStepBase::WaitForCompletionL(TRequestStatus& aSt, TInt aExpErrCode, const TDesC& aLogMsg)
{
INFO_PRINTF3(_L("%S: Waiting for completion with %d"), &aLogMsg, aExpErrCode);
User::WaitForRequest(aSt);
INFO_PRINTF3(_L("%S completed with status= %d"), &aLogMsg, aSt.Int());
TestL(aSt.Int(), aExpErrCode, aLogMsg);
}
void CSpudRSubConnTestStepBase::ReceiveOnSocketL(RSocket& aSocket, const TDesC& aLogMsg)
{
INFO_PRINTF2(_L("%S: Waiting to receive."), &aLogMsg);
TRequestStatus recvSt;
TBuf8<256> recvBuf;
TInetAddr srcAddr;
aSocket.RecvFrom(recvBuf, srcAddr, 0x0, recvSt);
WaitForCompletionL(recvSt, KErrNone, _L("Received on Socket"));
}
void CSpudRSubConnTestStepBase::VerifyBuffersEqualL(const TDesC8& aBuf1, const TDesC8& aBuf2)
{
if(0 != aBuf1.Compare(aBuf2))
{
INFO_PRINTF1(_L("Buffer 1 is not equal to Buffer 2. FAILURE."));
User::Leave(KErrCorrupt);
}
}
void CSpudRSubConnTestStepBase::WriteReadOnSocketL(RSocket& aSocket, const TDesC& aLogMsg)
{
INFO_PRINTF2(_L("%S: WriteReadOnSocketL"), &aLogMsg);
TRequestStatus wSt1;
TBuf8<KMaxMsgLen> writeBuf(_L8("WRITE READ"));
aSocket.Write(writeBuf, wSt1);
WaitForCompletionL(wSt1, KErrNone, _L("Write on Socket"));
TBuf8<KMaxMsgLen> readBuf;
TRequestStatus rSt;
aSocket.Read(readBuf, rSt);
WaitForCompletionL(rSt, KErrNone, _L("Read on Socket"));
VerifyBuffersEqualL(writeBuf, readBuf);
}
void CSpudRSubConnTestStepBase::SendRecvOnSocketL(RSocket& aSocket, TInetAddr& aDstAddr, const TDesC& aLogMsg)
{
INFO_PRINTF2(_L("%S: SendRecvOnSocketL"), &aLogMsg);
TBuf8<KMaxMsgLen> sendBuf(_L8("SEND RECEIVE"));
TRequestStatus sendSt;
aSocket.SendTo(sendBuf, aDstAddr, 0x0, sendSt);
WaitForCompletionL(sendSt, KErrNone, _L("Send on Socket"));
TBuf8<KMaxMsgLen> recvBuf;
TRequestStatus recvSt;
aSocket.RecvFrom(recvBuf, aDstAddr, 0x0, recvSt);
WaitForCompletionL(recvSt, KErrNone, _L("Receive on Socket"));
VerifyBuffersEqualL(recvBuf, sendBuf);
}
void CSpudRSubConnTestStepBase::RecvSendOnSocketL(RSocket& aSocket, const TDesC& aLogMsg)
{
INFO_PRINTF2(_L("%S: **Bounce: RecvSendOnSocket"), &aLogMsg);
TRequestStatus st;
TBuf8<KMaxMsgLen> recvBuf;
TInetAddr srcAddr;
aSocket.RecvFrom(recvBuf, srcAddr, 0x0, st);
WaitForCompletionL(st, KErrNone, _L("**Bounce: Receive on Socket"));
aSocket.SendTo(recvBuf, srcAddr, 0x0, st);
WaitForCompletionL(st, KErrNone, _L("**Bounce: Send on Socket"));
}
void CSpudRSubConnTestStepBase::OpenAndBindSocketL(RSocket& aSock, RConnection& aIface, TUint aLocalPort, const TDesC& aLogMsg)
{
INFO_PRINTF3(_L("%S: Opening and Binding to port= %d"), &aLogMsg, aLocalPort);
TInt ret = aSock.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
aIface);
TestL(ret, KErrNone, _L("Open UDP Socket"));
TInetAddr localAddr;
localAddr.SetPort(aLocalPort);
TestL(aSock.Bind(localAddr), KErrNone, _L("Bind Socket"));
}
//
/**
Used in lieu of proper network-based server
Open an interface, opens a socket on this interface, receives-sends udp (bounces) */
TVerdict CLoopbackPpp1::RunTestStepL()
{
// Figure out our name, so that the logging makes sense:
TBuf<64> ourName(_L("BOUNCE"));
ourName.AppendFormat(_L("[%x]"), this);
TInt iapId = -1;
ASSERT(GetIntFromConfig(ConfigSection(), _L("IapId"), iapId));
ASSERT(iapId > 0);
TCommDbConnPref pref;
pref.SetIapId(iapId);
RConnection iface;
ASSERT(KErrNone == iface.Open(iESock, KAfInet));
TRequestStatus startSt;
iface.Start(pref, startSt);
User::WaitForRequest(startSt);
INFO_PRINTF4(_L("%S: Interface on Iap ID =%d started with error=%d."), &ourName, iapId, startSt.Int());
User::LeaveIfError(startSt.Int());
TInt localPort = 0x0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("UdpEchoPort"), localPort));
ASSERT(localPort > 0x0);
RSocket bounceSock;
OpenAndBindSocketL(bounceSock, iface, static_cast<TUint>(localPort), ourName);
TInt iterations = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("Iterations"), iterations));
ASSERT(iterations > 0);
for(TInt iter = 0; iter < iterations; ++iter)
{
RecvSendOnSocketL(bounceSock, ourName);
}
bounceSock.Close();
iface.Close(); // Leave interface lingering, it will be nuked when the peer PPP terminates.
return EPass;
}
TBool CSpudRSubConnTestStepBase::ApplyQoSParametersL(RSubConnection& aPdpContext)
{
TInt qosParamSet = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("QoSParamSet"), qosParamSet));
ASSERT(qosParamSet >= 0);
switch(qosParamSet)
{
case 0:
return EFalse; // no qos parameters specified
case 2:
ApplyQoSParametersSet2L(aPdpContext);
return ETrue;
default:
ASSERT(EFalse);
return EFalse;
}
}
void CSpudRSubConnTestStepBase::ApplyQoSParametersSet2L(RSubConnection& aPdpContext)
{
RSubConParameterBundle qosParams;
CleanupClosePushL(qosParams);
// Create a container for QoS sub connection parameters (Param bundle takes ownership)
CSubConParameterFamily* qosFamily = CSubConParameterFamily::NewL(qosParams, KSubConQoSFamily);
// set class parameter
CSubConQosIPLinkR99ParamSet* ipParamsReq = CSubConQosIPLinkR99ParamSet::NewL(*qosFamily, CSubConParameterFamily::ERequested);
//The requested QoS parameters.
ipParamsReq->SetTrafficClass(RPacketQoS::ETrafficClassBackground);
ipParamsReq->SetMaxBitrateUplink(10);
ipParamsReq->SetMaxBitrateDownlink(50);
ipParamsReq->SetGuaBitrateDownlink(20);
ipParamsReq->SetGuaBitrateUplink(10);
ipParamsReq->SetMaxSduSize(1000);
ipParamsReq->SetResidualBitErrorRatio(RPacketQoS::EBERFourPerThousand);
ipParamsReq->SetSDUErrorRatio(RPacketQoS::ESDUErrorRatioOnePerThousand);
ipParamsReq->SetErroneousSDUDelivery(RPacketQoS::EErroneousSDUDeliveryNotRequired);
ipParamsReq->SetTrafficHandlingPriority(RPacketQoS::ETrafficPriorityUnspecified);
ipParamsReq->SetTransferDelay(3000);
ipParamsReq->SetDeliveryOrder(RPacketQoS::EDeliveryOrderNotRequired);
//The minimum Requested params
CSubConQosIPLinkR99ParamSet* ipParamsMinReq = CSubConQosIPLinkR99ParamSet::NewL(*qosFamily, CSubConParameterFamily::EAcceptable);
ipParamsMinReq->SetTrafficClass(RPacketQoS::ETrafficClassBackground);
ipParamsMinReq->SetGuaBitrateDownlink(20);
ipParamsMinReq->SetGuaBitrateUplink(8);
ipParamsMinReq->SetMaxBitrateDownlink(20);
ipParamsMinReq->SetMaxBitrateUplink(10);
ipParamsMinReq->SetMaxSduSize(200);
ipParamsMinReq->SetResidualBitErrorRatio(RPacketQoS::EBERFivePerHundred);
ipParamsMinReq->SetSDUErrorRatio(RPacketQoS::ESDUErrorRatioOnePerTen);
ipParamsMinReq->SetErroneousSDUDelivery(RPacketQoS::EErroneousSDUDeliveryNotRequired);
ipParamsMinReq->SetTrafficHandlingPriority(RPacketQoS::ETrafficPriorityUnspecified);
ipParamsMinReq->SetTransferDelay(4000);
ipParamsMinReq->SetDeliveryOrder(RPacketQoS::EDeliveryOrderNotRequired);
TInt err = aPdpContext.SetParameters(qosParams);
TestL(err, KErrNone, _L("Applied QoS Parameters"));
CleanupStack::PopAndDestroy(&qosParams);
}
/**
The test sequence:
Create the primary & secondary PDP contexts.
Send - Receive UDP over both of them.
Close everything
@leave if a test fails or there is an unexpected error */
TVerdict CUdp1::RunTestStepL()
{
TRequestStatus spudStartReq;
TCommDbConnPref spudPref;
spudPref.SetIapId(2);
OpenAndStartInterfaceL(iSpud, spudPref, spudStartReq, _L(">>>>>Starting SPUD NIF"));
WaitForCompletionL(spudStartReq, KErrNone, _L(">>>>>Starting SPUD NIF"));
TInt ret = iScndCtxSock1.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
iSpud);
TestL(ret, KErrNone, _L(">>>>>>>>Open UDP Socket, primary PDP context"));
// KSoUdpSynchronousSend option causes the UDP send operation to block when dynamic
// interface setup is in progress or when local flow control within the stack would otherwise
// cause the packet to be dropped. This is not strictly necessary since we've waited for KLinkLayerOpen,
// but who knows what's the timing between TCP/IP stack, Nifman, ESock is like...
TestL(iScndCtxSock1.SetOpt(KSoUdpSynchronousSend, KSolInetUdp, 1), KErrNone, _L("SetOpt Sync Send"));
// We must bind to a local address, and connect to a remote address,
// so that TFT is always generated with the same destination - source ports.
// Otherwise, SIM.TSY will reject TFT proposed.
TInt scndCtxSockLocalPort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("SecLocalPort"), scndCtxSockLocalPort));
ASSERT(scndCtxSockLocalPort > 0);
TInetAddr localAddr;
localAddr.SetPort(scndCtxSockLocalPort);
TestL(iScndCtxSock1.Bind(localAddr), KErrNone, _L(">>>>>Bind the Secondary PDP ctx socket"));
TInt scndCtxSockRemotePort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("SecRemotePort"),scndCtxSockRemotePort));
ASSERT(scndCtxSockRemotePort > 0);
TPtrC scndCtxSockRemoteAddr;
ASSERT(GetStringFromConfig(ConfigSection(), _L("SecRemoteIpAddr"), scndCtxSockRemoteAddr));
TInetAddr dstAddr1;
dstAddr1.SetPort(scndCtxSockRemotePort);
dstAddr1.Input(scndCtxSockRemoteAddr);
TRequestStatus connStatus;
iScndCtxSock1.Connect(dstAddr1, connStatus);
WaitForCompletionL(connStatus, KErrNone, _L(">>>>>>>Connect the Secondary PDP ctx socket"));
TInt sockErr = iPrimCtxSock1.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
iSpud);
TestL(sockErr, KErrNone, _L(">>>>>>Open Primary PDP ctx socket"));
TInt openErr = iSpudScndCtx1.Open(iESock,
RSubConnection::ECreateNew,
iSpud);
TestL(openErr, KErrNone, _L(">>>>>>>Open RSubConnection on SPUD"));
TRequestStatus subconNotifyStat;
TNotificationEventBuf eventBuf;
iSpudScndCtx1.EventNotification(eventBuf, ETrue, subconNotifyStat);
TBool waitForQos = ApplyQoSParametersL(iSpudScndCtx1);
TRequestStatus subconAddStat;
iSpudScndCtx1.Add(iScndCtxSock1, subconAddStat);
WaitForCompletionL(subconAddStat, KErrNone, _L(">>>>>>Transfer the Socket to 2ndary context"));
if(waitForQos)
{
WaitForCompletionL(subconNotifyStat, KErrNone, _L(">>>>>QoS Negotiation Completion on 2ndary context"));
}
else
{
iSpudScndCtx1.CancelEventNotification();
}
//*************************************************************************************************
User::After(3 * 1000000); // Give the loopback sockets a chance to bind & open,
// else we can end up with ICMP Destination (port) Unreachable.
// When used over WinTunnel, this is completely unnecessary.
//*************************************************************************************************
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 1"));
// Must address UDP on primary explicitly.
TInt primCtxSockRemotePort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("PrimRemotePort"),primCtxSockRemotePort));
ASSERT(primCtxSockRemotePort > 0);
TPtrC primCtxSockRemoteAddr;
ASSERT(GetStringFromConfig(ConfigSection(), _L("PrimRemoteIpAddr"), primCtxSockRemoteAddr));
TInetAddr primDstAddr1;
primDstAddr1.SetPort(primCtxSockRemotePort);
primDstAddr1.Input(primCtxSockRemoteAddr);
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Send - Receive on Primary PDP Context, 1"));
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 2"));
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Primary PDP Context, 2"));
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Primary PDP Context, 3"));
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 3"));
iSpud.Stop(); // nukes both contexts
// Everything will be cleaned up later.
return EPass;
}
/**
The test sequence:
Create the primary context
Init secondary SubConnection
Set up QoS params on secondary SubConnection
Create the secondary PDP contexts on secondary SubConnection.
Send - Receive UDP over both of them.
Close everything
@leave if a test fails or there is an unexpected error */
TVerdict CUdp2::RunTestStepL()
{
TRequestStatus spudStartReq;
TCommDbConnPref spudPref;
spudPref.SetIapId(2);
OpenAndStartInterfaceL(iSpud, spudPref, spudStartReq, _L(">>>>>Starting SPUD NIF"));
WaitForCompletionL(spudStartReq, KErrNone, _L(">>>>>Starting SPUD NIF"));
TInt openErr = iSpudScndCtx1.Open(iESock,
RSubConnection::ECreateNew,
iSpud);
TestL(openErr, KErrNone, _L(">>>>>>>Open RSubConnection on SPUD"));
TRequestStatus subconNotifyStat;
TNotificationEventBuf eventBuf;
iSpudScndCtx1.EventNotification(eventBuf, ETrue, subconNotifyStat);
TBool waitForQos = ApplyQoSParametersL(iSpudScndCtx1);
// Socket Open on Secondary SubConnection
TInt ret = iScndCtxSock1.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
iSpudScndCtx1);
TestL(ret, KErrNone, _L(">>>>>>>>Open UDP Socket, primary PDP context"));
// KSoUdpSynchronousSend option causes the UDP send operation to block when dynamic
// interface setup is in progress or when local flow control within the stack would otherwise
// cause the packet to be dropped. This is not strictly necessary since we've waited for KLinkLayerOpen,
// but who knows what's the timing between TCP/IP stack, Nifman, ESock is like...
TestL(iScndCtxSock1.SetOpt(KSoUdpSynchronousSend, KSolInetUdp, 1), KErrNone, _L("SetOpt Sync Send"));
// We must bind to a local address, and connect to a remote address,
// so that TFT is always generated with the same destination - source ports.
// Otherwise, SIM.TSY will reject TFT proposed by GUQoS.
TInt scndCtxSockLocalPort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("SecLocalPort"), scndCtxSockLocalPort));
ASSERT(scndCtxSockLocalPort > 0);
TInetAddr localAddr;
localAddr.SetPort(scndCtxSockLocalPort);
TestL(iScndCtxSock1.Bind(localAddr), KErrNone, _L(">>>>>Bind the Secondary PDP ctx socket"));
TInt scndCtxSockRemotePort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("SecRemotePort"),scndCtxSockRemotePort));
ASSERT(scndCtxSockRemotePort > 0);
TPtrC scndCtxSockRemoteAddr;
ASSERT(GetStringFromConfig(ConfigSection(), _L("SecRemoteIpAddr"), scndCtxSockRemoteAddr));
TInetAddr dstAddr1;
dstAddr1.SetPort(scndCtxSockRemotePort);
dstAddr1.Input(scndCtxSockRemoteAddr);
TRequestStatus connStatus;
iScndCtxSock1.Connect(dstAddr1, connStatus);
WaitForCompletionL(connStatus, KErrNone, _L(">>>>>>>Connect the Secondary PDP ctx socket"));
if(waitForQos)
{
WaitForCompletionL(subconNotifyStat, KErrNone, _L(">>>>>QoS Negotiation Completion on 2ndary context"));
}
else
{
iSpudScndCtx1.CancelEventNotification();
}
TInt sockErr = iPrimCtxSock1.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
iSpud);
TestL(sockErr, KErrNone, _L(">>>>>>Open Primary PDP ctx socket"));
//*************************************************************************************************
User::After(3 * 1000000); // Give the loopback sockets a chance to bind & open,
// else we can end up with ICMP Destination (port) Unreachable.
// When used over WinTunnel, this is completely unnecessary.
//*************************************************************************************************
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 1"));
// Must address UDP on primary explicitly.
TInt primCtxSockRemotePort = 0;
ASSERT(GetIntFromConfig(ConfigSection(), _L("PrimRemotePort"),primCtxSockRemotePort));
ASSERT(primCtxSockRemotePort > 0);
TPtrC primCtxSockRemoteAddr;
ASSERT(GetStringFromConfig(ConfigSection(), _L("PrimRemoteIpAddr"), primCtxSockRemoteAddr));
TInetAddr primDstAddr1;
primDstAddr1.SetPort(primCtxSockRemotePort);
primDstAddr1.Input(primCtxSockRemoteAddr);
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Send - Receive on Primary PDP Context, 1"));
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 2"));
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Primary PDP Context, 2"));
SendRecvOnSocketL(iPrimCtxSock1, primDstAddr1, _L(">>>>>>>Primary PDP Context, 3"));
WriteReadOnSocketL(iScndCtxSock1, _L(">>>>>>>Secondary PDP Context, 3"));
iSpud.Stop(); // nukes both contexts
// Everything will be cleaned up later.
return EPass;
}
TVerdict CUpperFlowOnLowerNifDown::RunTestStepL()
{
// Start the primary
TRequestStatus spudStartReq;
TCommDbConnPref spudPref;
spudPref.SetIapId(2);
OpenAndStartInterfaceL(iSpud, spudPref, spudStartReq, _L(">>>>>Starting SPUD NIF"));
// Start PPP peer for the primary
RConnection primCtxPppPeer;
TRequestStatus peerStartReq;
TCommDbConnPref peerPref;
peerPref.SetIapId(1);
OpenAndStartInterfaceL(primCtxPppPeer, peerPref, peerStartReq, _L(">>>>Starting PPP Peer for the primary context"));
WaitForCompletionL(spudStartReq, KErrNone, _L(">>>>>Starting SPUD NIF"));
WaitForCompletionL(peerStartReq, KErrNone, _L(">>>>>Starting PPP Peer for SPUD primary context"));
// Open socket on primary
TInt sockErr = iPrimCtxSock1.Open(iESock,
KAfInet,
KSockDatagram,
KProtocolInetUdp,
iSpud);
TestL(sockErr, KErrNone, _L(">>>>>>>>Open UDP Socket, primary PDP context"));
User::After(2 * 10000); // Let everything settle down.
// Stop PPP peer, triggerting LinkLayerDown on the primary
TInt stopErr = primCtxPppPeer.Stop();
ASSERT(KErrNone == stopErr); // If there is an error, the test was not setup correctly.
// At this point contxt deletion request is outstanding: SIM TSY will not complete it for a while.
// Send on primary socket: no way to verify where it blocked. Must inspect the logs.
User::After(5 * 1000000);
TInetAddr primDstAddr1;
primDstAddr1.SetPort(1060);
primDstAddr1.Input(_L("192.168.3.1"));
TBuf8<KMaxMsgLen> sendBuf(_L8("A packet to the La-La Land."));
TRequestStatus sendSt;
iPrimCtxSock1.SendTo(sendBuf, primDstAddr1, 0x0, sendSt);
WaitForCompletionL(sendSt, KErrNone, _L("Send on Socket")); // ESock completed the send, the packet
// still needs to percolate through the tcp/ip stack - GUQoS - SPUD.
User::After(30 * 1000000);
// SPUD panics if the upper layer tries to send on a flowed-off context.
return EPass; // If there was a failure, we'd leave or panic
// Cleanup everything later
}
/**
Brings up SPUD & PPP peer from the primary context, then stops Spud.
This test step is intended to be used in a combination with other steps, (including itself),
to verify how RConnection::Stop affects the behaviour of the system. */
TVerdict CSpudPppPrimaryStop::RunTestStepL()
{
TRequestStatus spudStartReq;
TCommDbConnPref spudPref;
spudPref.SetIapId(2);
OpenAndStartInterfaceL(iSpud, spudPref, spudStartReq, _L(">>>>>Starting SPUD NIF"));
RConnection primCtxPppPeer;
TRequestStatus peerStartReq;
TCommDbConnPref peerPref;
peerPref.SetIapId(1);
OpenAndStartInterfaceL(primCtxPppPeer, peerPref, peerStartReq, _L(">>>>Starting PPP Peer for the primary context"));
WaitForCompletionL(spudStartReq, KErrNone, _L(">>>>>Starting SPUD NIF"));
WaitForCompletionL(peerStartReq, KErrNone, _L(">>>>>Starting PPP Peer for SPUD primary context"));
TInt stopTypeInt = -1;
ASSERT(GetIntFromConfig(ConfigSection(), _L("StopType"), stopTypeInt));
RConnection::TConnStopType stopType = static_cast<RConnection::TConnStopType>(stopTypeInt);
INFO_PRINTF2(_L("Stopping Spud with stop type= %d (0 = EStopNormal, 1 = EStopAuthoritative)"), stopType);
ASSERT(RConnection::EStopNormal == stopType || RConnection::EStopAuthoritative == stopType);
TInt stopErr = iSpud.Stop(stopType);
INFO_PRINTF2(_L("Stopped Spud with error = %d"), stopErr);
ASSERT(KErrNone == stopErr); // If we have an errror, test was not set up / executed correctly.
// if stop was authoritative ppp wont do the leaving handshake, so peer also needs to be stopped
if (stopType == RConnection::EStopAuthoritative)
{
TInt stopErr = primCtxPppPeer.Stop(stopType);
INFO_PRINTF2(_L("Stopped peer with error = %d"), stopErr);
ASSERT(KErrNone == stopErr); // If we have an errror, test was not set up / executed correctly.
}
else
{
primCtxPppPeer.Close(); // No need to stop, peer should be shutting down as a result of Stop on Spud.
}
return EPass;
}