diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/rawipnif/src/RawIPFlow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/rawipnif/src/RawIPFlow.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,874 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Implements the CRawIPFlow class, which provides a central point for the NIF +// to communicate with NifMan and the BCA controllers. This class creates an interface +// to the IPv4 protocol when it is required. +// +// + +/** + @file +*/ + +#include +#include +#include +#include +#include +#include "IPv4Binder.h" +#include "IPv6Binder.h" +#include "RawIPFlow.h" +#include +#include +#include // for SAccessPointConfig +#include +#include +#include + +using namespace Messages; +using namespace MeshMachine; +using namespace ESock; + +#ifdef __FLOG_ACTIVE +//These variables are used only if flog is active. +_LIT8(KTcpDumpFirstTag,"TcpDump"); +static const TUint16 KTcpDumpLinkType = 12; +#endif + +CRawIPFlow::CRawIPFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf, CBttLogger* aTheLogger) +/** + * Constructor. + * + * @param aFactory Reference to the factory which created this object. + * @param aTheLogger The logging object, ownership is passed to this object + */ + : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf), + iTheLogger(aTheLogger), + iInitError(KErrNone), + iStarted(EFalse), + iStopping(EFalse) + { + LOG_NODE_CREATE(KNifSubDir, CRawIPFlow); + } + +void CRawIPFlow::ConstructL() +/** + * Second-phase constructor. Creates the Etel + * control engine + * + * @param aName The name of the NIF (unused) + */ + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tConstructL()"), this); + iBinderControl = new (ELeave) TBinderControlProxy(*this); + iBcaController = CBcaIoController::NewL(*this, iTheLogger); + } + +CRawIPFlow::~CRawIPFlow() +/** + * Destructor. Cancels and deletes all owned active objects. + */ + { + // Note that we don't delete iBinder because it's not owned by us. + delete iBcaController; + // This class also deletes the logging object + delete iTheLogger; + + ASSERT(iBinder == NULL); + + delete iBinderControl; + LOG_NODE_DESTROY(KNifSubDir, CRawIPFlow); + // Cleanup when stop was not called - harmless as it null's the pointer + __PACKETLOG_DELETE; + } + +void CRawIPFlow::StartFlowL() +/** + * Starts the Flow up. This process involves connecting to the BCA. When startup is + * complete, LinkLayerUp() will be called. + * + * Called in response to corresponding SCPR message. + * + * @return Allways KErrNone + */ + { + ASSERT(iStarting==EFalse); + iStarting = ETrue; + _LOG_L1C2(_L8("CRawIPFlow %08x:\tStartFlowL()"), this); + + // If there were any errors during earlier processing of the ProvisionConfig message + // then send an Error message in response to the StartFlow (because ProvisionConfig + // does not have a response code). + if (iProvisionError != KErrNone) + { + User::Leave(iProvisionError); + } + + // Retrieve Agent provisioned information only available at StartFlow time + DynamicProvisionConfigL(); + InitialiseL(MControllerObserver::EStart, KErrNone); + + //the name calculation should be done only if logging is enabled +#ifdef __FLOG_ACTIVE + const TUint KModemNameLen = KCommsDbSvrMaxColumnNameLength + 10; // need enough for ppp-XXX.txt - e.g. ppp-comm-1.txt, ppp-btcomm-10.txt etc + TBuf8 modemName; + + _LIT8(KDoubleColon, "::"); + + modemName.Copy(iProvision->GetPortName()); + const TInt pos = modemName.FindC((const TDesC8&)KDoubleColon); + if(pos != KErrNotFound) + { + modemName.Delete(pos, 2); + } + + //append time stamp + const TUint KTimeStampLen = 8; + TBuf8 logFileName; + + _LIT8(KTimeFormat, "%08X"); + TUint32 counter = User::FastCounter(); + logFileName.Format(KTimeFormat, counter); + + TRAPD(err,__PACKETLOG_NEWL(KTcpDumpFirstTag, logFileName, CPacketLogger::ETcpDump, KTcpDumpLinkType)); + if (err) + { + _LOG_L1C1(_L8("Trapped leave from __PACKETLOG_NEWL")); + } + + const TUint KLogTextLen = KModemNameLen+KTimeStampLen+30; + TBuf8 logText; + _LIT8(KLogTimeText, "TcpDump log file time stamp:"); + _LIT8(KLogModemText, " for modem:"); + logText.Append(KLogTimeText); + logText.Append(logFileName); + logText.Append(KLogModemText); + logText.Append(modemName); + _LOG_L1C1(logText); +#endif + } + + +void CRawIPFlow::LinkLayerUp() +/** + * This function is called when initialisation is complete and the Flow is + * ready to send/receive data. It notifies NifMan and the IP interface that it's + * ready to go. + */ + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tLinkLayerUp()"), this); + + iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef()); + + + iBinder->StartSending(); + iStarted = ETrue; + iStarting = EFalse; + } + +void CRawIPFlow::LinkLayerDown(TInt aError) +/** + * This function is called when the context has been deactivated and the NIF + * is ready to be deleted, or if there is an error on startup. Its job is to + * notify NifMan that the link has gone down, so it can delete the NIF. + * + * @param aError An error code to propagate to NifMan + */ + { + _LOG_L1C3(_L8("CRawIPFlow %08x:\tLinkLayerDown(aError %d)"), this, aError); + __PACKETLOG_DELETE; + + if (iStopping) + { + iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef()); + } + else if (iStarting) + { + iSubConnectionProvider.PostMessage(Id(), TEBase::TError(TCFServiceProvider::TStart::Id(), aError).CRef()); + } + else + { + iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, MNifIfNotify::EDisconnect).CRef()); + } + + iStarted = EFalse; + iStarting = EFalse; + iStopping = EFalse; + } + +void CRawIPFlow::StopFlow(TInt aError) +/** + * This function is called by NifMan to bring down the link. It starts + * the asynchronous context deactivation process; LinkLayerDown() will be + * called when the context has been deactivated. + * + * @param aError A code specifying why the link is to be brought down + * @param aAction The action to take: disconnect or reconnect + */ + { + _LOG_L1C3(_L8("CRawIPFlow %08x:\tStopFlow(aError %d)"), this, aError); + __PACKETLOG_DELETE; + iStopping = ETrue; + ShutDown(MControllerObserver::EInitialised, aError); + } + +TInt CRawIPFlow::SendPacket(RMBufChain& aPdu, TAny* /*aProtocol*/, + TUint16 /*aType*/) +/** + * Sends a packet, via the BCA controller. This method is protocol-agnostic, + * and is called by the IPv4 and IPv6 binder to actually send packets. + * + * @param aPdu The packet to send + * @return A standard error code + */ + { + _LOG_L1C4(_L8("CRawIPFlow %08x:\tSendPacket(): length=%d, blocked=%d"), + this, aPdu.Length() - aPdu.First()->Length(),iBlocked); + + TInt ret = MLowerDataSender::ESendBlocked; + if (!iBlocked) + { + __PACKETLOG_WRITE_PACKET(aPdu, 0); + ret = iBcaController->Send(aPdu); + } + else + { + //crude flow cntrl handling: drop.. + aPdu.Free(); + } + return ret; + } + +void CRawIPFlow::Process(RMBufChain& aPdu, TUint16 aProtocolCode) +/** + * Handles incoming packets which have been passed up from the BCA controller. + * If the IPv4 binder wants to process the packet, it hands it on; otherwise, + * the packet is binned. + * + * @param aPdu The incoming packet + */ + { + _LOG_L1C3(_L8("CRawIPFlow %08x:\tProcess() [aPdu length=%d]"), + this, aPdu.Length() - aPdu.First()->Length()); + + // If the packet has zero or negative length, bin it. + if ((aPdu.Length() - aPdu.First()->Length()) <= 0) + { + _LOG_L1C1(_L8("Dumped packet: illegal length")); + aPdu.Free(); + return; + } + + // See if the protocol interface wants the packet. + if (iBinder && iBinder->WantsProtocol(aProtocolCode)) + { + __PACKETLOG_WRITE_PACKET(aPdu, 0); + iBinder->Process(aPdu); + } + else + { + // The protocol didn't want the packet, so bin it. + _LOG_L1C2(_L8("Packet was not processed: freeing (protocol code: %X)"), + aProtocolCode); + if (iBinder == NULL) + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tProcess(): NOTE: Binder not present"), this); + } + aPdu.Free(); + } + } + +void CRawIPFlow::ResumeSending() +/** + * Notifies the protocol interface that it can resume sending packets. + */ + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tResumeSending()"), this); + + if (iBinder) + { + iBinder->StartSending(); + } + else + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tResumeSending(): NOTE: Binder not present"), this); + } + } + +void CRawIPFlow::InitialiseL(TInitialisationState aState, TInt aError) +/** + * This method controls the initialisation sequence of the different modules + * in the Flow. When a module completes all the initialisation tasks it will + * call again this method with the new state. If an error occurs then the + * ShutDown() method will be called. + * + * @param aState The current initialisation step + * @param aError A possible error + */ + { + _LOG_L1C4(_L8("CRawIPFlow %08x:\tInitialiseL(aState %d, aError %d)"), + this, aState, aError); + + if (aError != KErrNone) + { + _LOG_L2C2(_L8(" *** FAILED to initialise NIF *** Error =%d"),aError); + + // Initialise shutdown sequence + switch (aState) + { + case MControllerObserver::EBcaController: + ShutDown(MControllerObserver::EInitialised, aError); + break; + default: + _LOG_L2C3(_L8("ERROR CRawIPFlow: Unknown state:%d in NIF: %S"), aState, &KNifName); + User::Leave(KErrUnknown); + break; + } + return; + } + + switch (aState) + { + case MControllerObserver::EStart: + { + // Update local state from TSY information originally from Agent. + GetBinder()->UpdateContextConfigL(*iAgentProvision->iGprsConfig); + GetBinder()->UpdateConnectionSpeed(iAgentProvision->iConnectionSpeed); + + _LOG_L1C2(_L8("Port details %S"), &iProvision->GetPortName()); + iBcaController->SetPort(iProvision->GetPortName()); + + _LOG_L1C3(_L8("bcaName details %S,%S"),&iProvision->GetBCAStack(), &iProvision->GetBCAName()); + iBcaController->SetBcaStackAndName(iProvision->GetBCAStack(), iProvision->GetBCAName()); + + _LOG_L1C2(_L8("IAP ID details %u"), iProvision->GetIAPid()); + iBcaController->SetIapId(iProvision->GetIAPid()); + + UpdateContextState(RPacketContext::EStatusActive, KErrNone); + + iBcaController->StartL(); + } + break; + case MControllerObserver::EBcaController: + _LOG_L1C1(_L8(" ***** NIF INITIALISED *****")); + LinkLayerUp(); + break; + default: + _LOG_L2C3(_L8("ERROR CRawIPFlow: Unknown state:%d in NIF: %S"), aState, &KNifName); + User::Leave(KErrUnknown); + break; + } + } + +void CRawIPFlow::ShutDown(TInitialisationState aState, TInt aError) +/** + * This method controls the shutdown sequence of the different modules + * in the Flow. When a module completes all the shutdown tasks it will + * call again this method with the new state. + * + * @param aState The current state + * @param aError A possible error (only during initialisation) + */ + { + _LOG_L1C4(_L8("CRawIPFlow %08x:\tShutDown(aState %d, aError %d)"), + this, aState, aError); + + if (aError != KErrNone) + { + // Flow is shutting down due to an error. + // The error code must be stored in order to call linklayer down + // passing that value + iInitError = aError; + } + + switch (aState) + { + case MControllerObserver::EInitialised: + iBcaController->Stop(aError); + break; + case MControllerObserver::EBcaController: + LinkLayerDown(iInitError); + break; + default: + _LOG_L2C1(_L8("ERROR CRawIPFlow: Unknown Shutdown step")); + _BTT_PANIC(KNifName,KNifUnknownShutDownState); + break; + } + } + +CBinderBase* CRawIPFlow::GetBinder() +/** + * Returns a pointer to the Binder class + * + * @return a pointer to a CBinderBase derived class + */ + { + return iBinder; + } + +CBcaIoController* CRawIPFlow::GetBcaController() +/** + * Returns a pointer to the CBcaIoController class + * + * @return a pointer to CBcaIoController + */ + { + return iBcaController; + } + +void CRawIPFlow::UpdateContextState( + RPacketContext::TContextStatus aState, TInt /*aError*/) +/** + * Updates the state of the iContextState variable + * + * @param aState The new state + * @param aError A possible error + */ + { + _LOG_L1C3(_L8("CRawIPFlow %08x:\tUpdateContextState(aState %d)"), this, aState); + + // Note that we do not need to close the Flow down if there's been an + // error, as the context state machine will do this for us. + + iContextStatus = aState; + } + +// ===================================================================================== +// +// CSubConnectionFlowBase +// + +MFlowBinderControl* CRawIPFlow::DoGetBinderControlL() + { + return iBinderControl; + } + +// ===================================================================================== +// +// MFlowBinderControl methods +// + +MLowerControl* CRawIPFlow::GetControlL(const TDesC8& aProtocol) + { +#ifdef __BTT_LOGGING__ + //TBuf8<256> debugBuffer; + //debugBuffer.Copy(aProtocol); + _LOG_L1C3(_L8("CRawIPFlow %08x:\tGetControlL(aProtocol %S)"), this, &aProtocol); +#endif + + // IPv4 and ICMP Protocols + if (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0) + { + if (!iBinder) + { + iBinder = new (ELeave) CIPv4Binder(*this, iTheLogger); +#ifdef RAWIP_HEADER_APPENDED_TO_PACKETS + iBcaController->SetType(KIp4FrameType); +#endif // RAWIP_HEADER_APPENDED_TO_PACKETS + } + else + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tGetControlL(): IPv4 binder already exists"), this); + } + } + // IPv6 Protocol + else if (aProtocol.CompareF(KDescIp6()) == 0) + { + if (!iBinder) + { + iBinder = new (ELeave) CIPv6Binder(*this, iTheLogger); +#ifdef RAWIP_HEADER_APPENDED_TO_PACKETS + iBcaController->SetType(KIp6FrameType); +#endif // RAWIP_HEADER_APPENDED_TO_PACKETS + } + else + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tGetControlL(): IPv6 binder already exists"), this); + } + } + else + { + User::Leave(KErrNotSupported); + } + + return iBinder; + } + +MLowerDataSender* CRawIPFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl) +/** + * Binds upper CFProtocol to this CFProtocol + * + * @param aUpperReceiver A pointer to Upper layer Receive class + * @param aUpperControl A pointer to Upper layer control class + */ + { +#ifndef _DEBUG + (void) aProtocol; +#endif + + ASSERT (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0 + || aProtocol.CompareF(KDescIp6()) == 0); + ASSERT(iBinder); + + iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef()); + return iBinder->Bind(aReceiver, aControl); + } + +void CRawIPFlow::Unbind(MUpperDataReceiver* aUpperReceiver, MUpperControl* aUpperControl) + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tUnbind()"), this); + + ASSERT(iBinder); + iBinder->Unbind(aUpperReceiver, aUpperControl); + + delete iBinder; + iBinder = NULL; + + SendDataClientIdleIfNoClients(); + } + + +void CRawIPFlow::SendDataClientIdleIfNoClients() + { + if (iBinder == NULL) + { + iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef()); + } + } + +CSubConnectionFlowBase* CRawIPFlow::Flow() +/** +Return the Flow corresponding to the MFlowBinderControl +*/ + { + return this; + } + +// ===================================================================================== +// +// Messages::ANode +// + +void CRawIPFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) + { + CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); + + if (aMessage.IsMessage()) + { + SubConnectionError(static_cast(aMessage).iValue); + } + else if (TEChild::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TEChild::TDestroy::EId : + Destroy(); + break; + default: +//TODO - logging + ASSERT(EFalse); + } + } + else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TCFDataClient::TStart::EId : + StartFlowL(); + break; + case TCFDataClient::TStop::EId : + StopFlow(static_cast(aMessage).iValue); + break; + case TCFDataClient::TProvisionConfig::EId: + ProvisionConfig(static_cast(aMessage).iConfig); + break; + case TCFDataClient::TBindTo::EId: + { + TCFDataClient::TBindTo& bindToReq = message_cast(aMessage); + if (!bindToReq.iNodeId.IsNull()) + { + User::Leave(KErrNotSupported); + } + RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); + } + break; + default: +//TODO - logging + ASSERT(EFalse); + } + } + else if (TCFFlow::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TCFFlow::TBlock::EId : + iBlocked = ETrue; + break; + case TCFFlow::TUnBlock::EId : + iBlocked = EFalse; + if (iBinder) + { + iBinder->StartSending(); + } + break; + case TCFFlow::TRejoin::EId: + { + TCFFlow::TRejoin& rejoinMsg = message_cast(aMessage); + TDefaultFlowFactoryQuery query(rejoinMsg.iNodeId); + CRawIPFlow* otherFlow = static_cast(Factory().Find(query)); + ASSERT(otherFlow); + + //This rather ugly looking snipped of code implements + //the scenario whereat the network tears down the default + //scpr and the default scpr selects a new default amongst + //the non-default and subsequently performs a transparant + //swap - i.e.: the upper layer perceives this as a + //non-default going down. Since the datapath is pre-bound + //to the flow representing the default, the datapath needs + //to perform a transparent swap too, so that the upper layer + //doesn't notice anything. It does that by swapping the + //flows below the binders. + CBinderBase* localBinder = iBinder; + CBttLogger* logger = localBinder->iTheLogger; + + TBinderControlProxy* localBinderControl = iBinderControl; + iBinder = otherFlow->iBinder; + otherFlow->iBinder->ChangeFlow(*this); + localBinder->ChangeFlow(*otherFlow); + otherFlow->iBinder = localBinder; + iBinderControl = otherFlow->iBinderControl; + otherFlow->iBinderControl = localBinderControl; + otherFlow->iBinderControl->iFlow = otherFlow; + iBinderControl->iFlow = this; + + iBinder->iTheLogger = logger; + + iSubConnectionProvider.Close(); + iSubConnectionProvider.Open(address_cast(rejoinMsg.iNodeId)); + } + break; + default: +//TODO - logging + ASSERT(EFalse); + } + } + else if (TLinkMessage::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TLinkMessage::TAgentToFlowNotification::EId: + { + TLinkMessage::TAgentToFlowNotification& msg = static_cast(aMessage); + Notification(msg.iValue); + break; + } + default: + ASSERT(EFalse); + } + } + else // not a recognised realm or message + { + ASSERT(EFalse); + } + } + + +// ===================================================================================== +// +// Methods for handling incoming SCPR messages +// + +void CRawIPFlow::SubConnectionGoingDown() + { + } + +void CRawIPFlow::SubConnectionError(TInt /*aError*/) + { + } + +/* +Provisioning description for RawIp CFProtocol Flow: + +- on receipt of the ProvisionConfig message, the pointer contained within is stored + in iAccessPointConfig and the provisioning information contained within it is validated: + - CBCAProvision must be present. It is added by the RawIpMCPr and populated from CommsDat. A pointer to it + is stored in iProvision. + if any are missing, an error is stored in iProvisionError and sent in response to the StartFlow + message later on (ProvisionConfig has no response). + +- on receipt of the StartFlow message, further provisioning information is retrieved: + - CIPConfig must be present. It is added by the RawIpMCPr and populated from CommsDat. The binder retrieves + individual fields from it. + - CRawIpAgentConfig must be present. It is added by the RawIpAgentHandler and populated via calls + to the Agent. A pointer to it is stored in iAgentProvision. Note that the iGprsConfig field + is a pointer to a (large) structure in the Agent (see CRawIpAgentHandler). + if any of the above are missing, an Error message is signalled back to the SCPr in response + to the StartFlow. +*/ + +void CRawIPFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData) +/** +Handle ProvisionConfig message from SCPR. + +Just save the pointer for now - validate it later on StartFlow. + +@param aData provisioning pointer from message +*/ + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tProvisionConfig()"), this); + + AccessPointConfig().Close(); + AccessPointConfig().Open(aConfigData); + + iProvision = static_cast(AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(CBCAProvision::EUid, CBCAProvision::ETypeId))); + + } + +void CRawIPFlow::DynamicProvisionConfigL() +/** +Retrieve provisioning information available only at StartFlow time. +*/ + { + if (iProvision == NULL) + { + _LOG_L1C1(_L8("CRawIPFlow:\tProvisionConfigL() - CBCAProvision config incomplete")); + iProvisionError = KErrCorrupt; + return; + } + + ASSERT(iAgentProvision == NULL); + iAgentProvision = static_cast(AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(CRawIpAgentConfig::EUid, CRawIpAgentConfig::ETypeId))); + + if (iAgentProvision == NULL) + { + User::Leave(KErrCorrupt); + } + + const CIPConfig* wcdmaIpProvision = static_cast(AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(CIPConfig::EUid, CIPConfig::ETypeId))); + if (wcdmaIpProvision == NULL) + { + _LOG_L1C2(_L8("CRawIPFlow %08x:\tDynamicProvisionConfigL() - WCDMA config incomplete"), this); + iProvisionError = KErrCorrupt; + return; + } + // Pass pointer to binder specific provisioning information to binder + if (iBinder) + { + iBinder->SetProvision(*wcdmaIpProvision); + } + } + + +void CRawIPFlow::Destroy() +/** +Handle Destroy message from SCPR. +*/ + { + DeleteThisFlow(); + } + +void CRawIPFlow::Notification(TInt aEvent) +/** +Handle Generic Link Tier messages from SCPR. + +These used to be implemented as Agent <-> NIF Notifications, hence the method name to promote +some historical understanding. +*/ + { + _LOG_L1C3(_L8("CRawIPFlow %08x:\tNotification(aEvent %d)"), this, aEvent); + + switch (aEvent) + { + case EAgentToNifEventTypeDisableTimers: //GPRS suspension + { + _LOG_L1C1(_L8("CRawIPFlow::Received Suspend from Agent...")); + + // Let the BCA controller know that data can no longer be sent over + // the PDP context. + iBcaController->UpdateContextStateFlag(EFalse); + + break; + } + + case EAgentToNifEventTypeEnableTimers: //GPRS resumption + { + _LOG_L1C1(_L8("CRawIPFlow::Received Resume from Agent...")); + iBcaController->UpdateContextStateFlag(ETrue); + + break; + } + + case (EAgentToNifEventTypeDisableConnection) : + { + // This is handled by NIFMAN and passed to Flow as a Stop() call + _LOG_L1C1(_L8("CRawIPFlow::Received Disable connection from Agent...")); + break; + } + + default : + { + _LOG_L1C2(_L8("CRawIPFlow::Received Notification [%d] from Agent..."), aEvent); + break; + } + }//endswitch + } + + +ESock::MLowerControl* CRawIPFlow::TBinderControlProxy::GetControlL(const TDesC8& aProtocol) + { + return RawIPFlow().GetControlL(aProtocol); + } + +ESock::MLowerDataSender* CRawIPFlow::TBinderControlProxy::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) + { + return RawIPFlow().BindL(aProtocol, aReceiver, aControl); + } + +void CRawIPFlow::TBinderControlProxy::Unbind(ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) + { + return RawIPFlow().Unbind(aReceiver, aControl); + } + +CSubConnectionFlowBase* CRawIPFlow::TBinderControlProxy::Flow() + { + return iFlow; + } + +// ===================================================================================== +// +// Utility functions +// + +void CRawIPFlow::PostProgressMessage(TInt aStage, TInt aError) + { + iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange( aStage, aError)).CRef()); + } + +// +// NOTE: +// Attribute table should be in the control side module that instantiates CRawIpProvision. +// RawIP CFProtocol does not instantiate the CRawIpProvision object, so does not need to +// define the attribute tables. The attribute table can therefore be placed directly into +// the control side module. +// +// The reason for this is to save splitting RawIP CFProtocol into two DLL's - ECOM and Main - +// just for control side module to link against Main DLL to retrieve the attribute table. +// In fact, it can be placed into control side module as "START_ATTRIBUTE_TABLE" rather +// than "EXPORT_START_ATTRIBUTE_TABLE". In fact, do we just need "TYPEID_TABLE" ? +// +// EXPORT_START_ATTRIBUTE_TABLE(CRawIpProvision, KRawIpConfigUid, KRawIpConfigType) +// END_ATTRIBUTE_TABLE()