telephonyprotocols/rawipnif/src/RawIPFlow.cpp
changeset 0 3553901f7fa8
child 5 7ef16719d8cb
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the CRawIPFlow class, which provides a central point for the NIF
       
    15 // to communicate with NifMan and the BCA controllers. This class creates an interface
       
    16 // to the IPv4 protocol when it is required.
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22 */
       
    23 
       
    24 #include <f32file.h>
       
    25 #include <nifman.h>
       
    26 #include <nifmbuf.h>
       
    27 #include <in_iface.h>
       
    28 #include <nifvar.h>
       
    29 #include "IPv4Binder.h"
       
    30 #include "IPv6Binder.h"
       
    31 #include "RawIPFlow.h"
       
    32 #include <comms-infras/linkprovision.h>
       
    33 #include <comms-infras/linkmessages.h>
       
    34 #include <comms-infras/ss_metaconnprov.h>					// for SAccessPointConfig
       
    35 #include <elements/nm_messages_base.h>
       
    36 #include <elements/nm_messages_child.h>
       
    37 #include <comms-infras/ss_nodemessages_flow.h>
       
    38 
       
    39 using namespace Messages;
       
    40 using namespace MeshMachine;
       
    41 using namespace ESock;
       
    42 
       
    43 #ifdef __FLOG_ACTIVE
       
    44 //These variables are used only if flog is active.
       
    45 _LIT8(KTcpDumpFirstTag,"TcpDump");
       
    46 static const TUint16 KTcpDumpLinkType = 12;
       
    47 #endif
       
    48 
       
    49 CRawIPFlow::CRawIPFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf, CBttLogger* aTheLogger)
       
    50 /**
       
    51  * Constructor.
       
    52  *
       
    53  * @param aFactory Reference to the factory which created this object.
       
    54  * @param aTheLogger The logging object, ownership is passed to this object
       
    55  */
       
    56 	: CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf),
       
    57 	  iTheLogger(aTheLogger),
       
    58 	  iInitError(KErrNone),
       
    59 	  iStarted(EFalse),
       
    60 	  iStopping(EFalse)
       
    61 	{
       
    62 	LOG_NODE_CREATE(KNifSubDir, CRawIPFlow);
       
    63 	}
       
    64 
       
    65 void CRawIPFlow::ConstructL()
       
    66 /**
       
    67  * Second-phase constructor. Creates the Etel
       
    68  * control engine
       
    69  *
       
    70  * @param aName The name of the NIF (unused)
       
    71  */
       
    72 	{
       
    73 	_LOG_L1C2(_L8("CRawIPFlow %08x:\tConstructL()"), this);
       
    74     iBinderControl = new (ELeave) TBinderControlProxy(*this);
       
    75 	iBcaController = CBcaIoController::NewL(*this, iTheLogger);
       
    76 	}
       
    77 
       
    78 CRawIPFlow::~CRawIPFlow()
       
    79 /**
       
    80  * Destructor. Cancels and deletes all owned active objects.
       
    81  */
       
    82 	{
       
    83 	// Note that we don't delete iBinder because it's not owned by us.
       
    84 	delete iBcaController;
       
    85 	// This class also deletes the logging object
       
    86 	delete iTheLogger;
       
    87 
       
    88 	ASSERT(iBinder == NULL);
       
    89 	
       
    90 	delete iBinderControl;	
       
    91 	LOG_NODE_DESTROY(KNifSubDir, CRawIPFlow);
       
    92 	// Cleanup when stop was not called - harmless as it null's the pointer
       
    93 	__PACKETLOG_DELETE;
       
    94 	}
       
    95 
       
    96 void CRawIPFlow::StartFlowL()
       
    97 /**
       
    98  * Starts the Flow up. This process involves connecting to the BCA.  When startup is
       
    99  * complete, LinkLayerUp() will be called.
       
   100  *
       
   101  * Called in response to corresponding SCPR message.
       
   102  *
       
   103  * @return Allways KErrNone
       
   104  */
       
   105 	{
       
   106 	ASSERT(iStarting==EFalse);
       
   107 	iStarting = ETrue;
       
   108 	_LOG_L1C2(_L8("CRawIPFlow %08x:\tStartFlowL()"), this);
       
   109 
       
   110 	// If there were any errors during earlier processing of the ProvisionConfig message
       
   111 	// then send an Error message in response to the StartFlow (because ProvisionConfig
       
   112 	// does not have a response code).
       
   113 	if (iProvisionError != KErrNone)
       
   114 		{
       
   115 		User::Leave(iProvisionError);
       
   116 		}
       
   117 
       
   118 	// Retrieve Agent provisioned information only available at StartFlow time
       
   119 	DynamicProvisionConfigL();
       
   120 	InitialiseL(MControllerObserver::EStart, KErrNone);
       
   121 
       
   122 	//the name calculation should be done only if logging is enabled
       
   123 #ifdef __FLOG_ACTIVE
       
   124 	const TUint KModemNameLen = KCommsDbSvrMaxColumnNameLength + 10;  // need enough for ppp-XXX.txt - e.g. ppp-comm-1.txt, ppp-btcomm-10.txt etc
       
   125 	TBuf8<KModemNameLen> modemName;
       
   126 
       
   127 	_LIT8(KDoubleColon, "::");
       
   128 
       
   129 	modemName.Copy(iProvision->GetPortName());
       
   130 	const TInt pos = modemName.FindC((const TDesC8&)KDoubleColon);
       
   131 	if(pos != KErrNotFound)
       
   132 		{
       
   133 		modemName.Delete(pos, 2);
       
   134 		}
       
   135 
       
   136 	//append time stamp
       
   137 	const TUint KTimeStampLen = 8;
       
   138 	TBuf8<KTimeStampLen> logFileName;
       
   139 
       
   140 	_LIT8(KTimeFormat, "%08X");
       
   141 	TUint32 counter = User::FastCounter();
       
   142 	logFileName.Format(KTimeFormat, counter);
       
   143 
       
   144 	TRAPD(err,__PACKETLOG_NEWL(KTcpDumpFirstTag, logFileName, CPacketLogger::ETcpDump, KTcpDumpLinkType));
       
   145 	if (err)
       
   146 		{
       
   147 		_LOG_L1C1(_L8("Trapped leave from __PACKETLOG_NEWL"));
       
   148 		}
       
   149 
       
   150 	const TUint KLogTextLen = KModemNameLen+KTimeStampLen+30;
       
   151 	TBuf8<KLogTextLen> logText;
       
   152 	_LIT8(KLogTimeText, "TcpDump log file time stamp:");
       
   153 	_LIT8(KLogModemText, " for modem:");
       
   154 	logText.Append(KLogTimeText);
       
   155 	logText.Append(logFileName);
       
   156 	logText.Append(KLogModemText);
       
   157 	logText.Append(modemName);
       
   158 	_LOG_L1C1(logText);
       
   159 #endif
       
   160 	}
       
   161 
       
   162 
       
   163 void CRawIPFlow::LinkLayerUp()
       
   164 /**
       
   165  * This function is called when initialisation is complete and the Flow is
       
   166  * ready to send/receive data. It notifies NifMan and the IP interface that it's
       
   167  * ready to go.
       
   168  */
       
   169 	{
       
   170 	_LOG_L1C2(_L8("CRawIPFlow %08x:\tLinkLayerUp()"), this);
       
   171 
       
   172 	iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
       
   173 
       
   174 
       
   175 	iBinder->StartSending();
       
   176 	iStarted = ETrue;
       
   177 	iStarting = EFalse;
       
   178 	}
       
   179 
       
   180 void CRawIPFlow::LinkLayerDown(TInt aError)
       
   181 /**
       
   182  * This function is called when the context has been deactivated and the NIF
       
   183  * is ready to be deleted, or if there is an error on startup. Its job is to
       
   184  * notify NifMan that the link has gone down, so it can delete the NIF.
       
   185  *
       
   186  * @param aError An error code to propagate to NifMan
       
   187  */
       
   188 	{
       
   189 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tLinkLayerDown(aError %d)"), this, aError);
       
   190 	__PACKETLOG_DELETE;
       
   191 
       
   192 	if (iStopping)
       
   193 		{
       
   194 		iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef());
       
   195 		}
       
   196     else if (iStarting)
       
   197 		{
       
   198 		iSubConnectionProvider.PostMessage(Id(), TEBase::TError(TCFServiceProvider::TStart::Id(), aError).CRef());
       
   199 		}
       
   200 	else
       
   201 		{
       
   202 		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, MNifIfNotify::EDisconnect).CRef());
       
   203 		}
       
   204 
       
   205     iStarted = EFalse;
       
   206     iStarting = EFalse;
       
   207     iStopping = EFalse;
       
   208 	}
       
   209 
       
   210 void CRawIPFlow::StopFlow(TInt aError)
       
   211 /**
       
   212  * This function is called by NifMan to bring down the link. It starts
       
   213  * the asynchronous context deactivation process; LinkLayerDown() will be
       
   214  * called when the context has been deactivated.
       
   215  *
       
   216  * @param aError A code specifying why the link is to be brought down
       
   217  * @param aAction The action to take: disconnect or reconnect
       
   218  */
       
   219 	{
       
   220 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tStopFlow(aError %d)"), this, aError);
       
   221 	__PACKETLOG_DELETE;
       
   222 	iStopping = ETrue;
       
   223 	ShutDown(MControllerObserver::EInitialised, aError);
       
   224 	}
       
   225 
       
   226 TInt CRawIPFlow::SendPacket(RMBufChain& aPdu, TAny* /*aProtocol*/,
       
   227 							   TUint16 /*aType*/)
       
   228 /**
       
   229  * Sends a packet, via the BCA controller. This method is protocol-agnostic,
       
   230  * and is called by the IPv4 and IPv6 binder to actually send packets.
       
   231  *
       
   232  * @param aPdu The packet to send
       
   233  * @return A standard error code
       
   234  */
       
   235 	{
       
   236 	_LOG_L1C4(_L8("CRawIPFlow %08x:\tSendPacket(): length=%d, blocked=%d"),
       
   237 		this, aPdu.Length() - aPdu.First()->Length(),iBlocked);
       
   238 
       
   239     TInt ret = MLowerDataSender::ESendBlocked;
       
   240 	if (!iBlocked)
       
   241     	{
       
   242     	__PACKETLOG_WRITE_PACKET(aPdu, 0);
       
   243     	ret = iBcaController->Send(aPdu);
       
   244     	}
       
   245     else
       
   246         {
       
   247         //crude flow cntrl handling: drop..
       
   248         aPdu.Free();
       
   249         }
       
   250 	return ret;
       
   251 	}
       
   252 
       
   253 void CRawIPFlow::Process(RMBufChain& aPdu, TUint16 aProtocolCode)
       
   254 /**
       
   255  * Handles incoming packets which have been passed up from the BCA controller.
       
   256  * If the IPv4 binder wants to process the packet, it hands it on; otherwise,
       
   257  * the packet is binned.
       
   258  *
       
   259  * @param aPdu The incoming packet
       
   260  */
       
   261 	{
       
   262 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tProcess() [aPdu length=%d]"),
       
   263 		this, aPdu.Length() - aPdu.First()->Length());
       
   264 
       
   265 	// If the packet has zero or negative length, bin it.
       
   266 	if ((aPdu.Length() - aPdu.First()->Length()) <= 0)
       
   267 		{
       
   268 		_LOG_L1C1(_L8("Dumped packet: illegal length"));
       
   269 		aPdu.Free();
       
   270 		return;
       
   271 		}
       
   272 
       
   273 	// See if the protocol interface wants the packet.
       
   274 	if (iBinder && iBinder->WantsProtocol(aProtocolCode))
       
   275 		{
       
   276 		__PACKETLOG_WRITE_PACKET(aPdu, 0);
       
   277 		iBinder->Process(aPdu);
       
   278 		}
       
   279 	else
       
   280 		{
       
   281 		// The protocol didn't want the packet, so bin it.
       
   282 		_LOG_L1C2(_L8("Packet was not processed: freeing (protocol code: %X)"),
       
   283 			aProtocolCode);
       
   284 		if (iBinder == NULL)
       
   285 			{
       
   286 			_LOG_L1C2(_L8("CRawIPFlow %08x:\tProcess(): NOTE: Binder not present"), this);
       
   287 			}
       
   288 		aPdu.Free();
       
   289 		}
       
   290 	}
       
   291 
       
   292 void CRawIPFlow::ResumeSending()
       
   293 /**
       
   294  * Notifies the protocol interface that it can resume sending packets.
       
   295  */
       
   296 	{
       
   297 	_LOG_L1C2(_L8("CRawIPFlow %08x:\tResumeSending()"), this);
       
   298 
       
   299 	if (iBinder)
       
   300 		{
       
   301 		iBinder->StartSending();
       
   302 		}
       
   303 	else
       
   304 		{
       
   305 		_LOG_L1C2(_L8("CRawIPFlow %08x:\tResumeSending(): NOTE: Binder not present"), this);
       
   306 		}
       
   307 	}
       
   308 
       
   309 void CRawIPFlow::InitialiseL(TInitialisationState aState, TInt aError)
       
   310 /**
       
   311  * This method controls the initialisation sequence of the different modules
       
   312  * in the Flow. When a module completes all the initialisation tasks it will
       
   313  * call again this method with the new state. If an error occurs then the
       
   314  * ShutDown() method will be called.
       
   315  *
       
   316  * @param aState The current initialisation step
       
   317  * @param aError A possible error
       
   318  */
       
   319 	{
       
   320 	_LOG_L1C4(_L8("CRawIPFlow %08x:\tInitialiseL(aState %d, aError %d)"),
       
   321 		this, aState, aError);		
       
   322 
       
   323 	if (aError != KErrNone)
       
   324 		{
       
   325 		_LOG_L2C2(_L8("  *** FAILED to initialise NIF *** Error =%d"),aError);
       
   326 
       
   327 		// Initialise shutdown sequence
       
   328 		switch (aState)
       
   329 		{
       
   330 		case MControllerObserver::EBcaController:
       
   331 			ShutDown(MControllerObserver::EInitialised, aError);
       
   332 			break;
       
   333 		default:
       
   334 			_LOG_L2C3(_L8("ERROR CRawIPFlow: Unknown state:%d in NIF: %S"), aState, &KNifName);
       
   335 			User::Leave(KErrUnknown);
       
   336 			break;
       
   337 			}
       
   338 		return;
       
   339 		}
       
   340 
       
   341 	switch (aState)
       
   342 		{
       
   343 	case MControllerObserver::EStart:
       
   344 		{
       
   345 		// Update local state from TSY information originally from Agent.
       
   346 		GetBinder()->UpdateContextConfigL(*iAgentProvision->iGprsConfig);
       
   347 		GetBinder()->UpdateConnectionSpeed(iAgentProvision->iConnectionSpeed);
       
   348 
       
   349 		_LOG_L1C2(_L8("Port details %S"), &iProvision->GetPortName());
       
   350 		iBcaController->SetPort(iProvision->GetPortName());
       
   351 
       
   352 		_LOG_L1C3(_L8("bcaName details %S,%S"),&iProvision->GetBCAStack(), &iProvision->GetBCAName());
       
   353 		iBcaController->SetBcaStackAndName(iProvision->GetBCAStack(), iProvision->GetBCAName());
       
   354 
       
   355 		_LOG_L1C2(_L8("IAP ID details %u"), iProvision->GetIAPid());
       
   356 		iBcaController->SetIapId(iProvision->GetIAPid());
       
   357 
       
   358 		UpdateContextState(RPacketContext::EStatusActive, KErrNone);
       
   359 
       
   360 		iBcaController->StartL();
       
   361 		}
       
   362 		break;
       
   363 	case MControllerObserver::EBcaController:
       
   364 		_LOG_L1C1(_L8("  ***** NIF INITIALISED *****"));
       
   365 		LinkLayerUp();
       
   366 		break;
       
   367 	default:
       
   368 		_LOG_L2C3(_L8("ERROR CRawIPFlow: Unknown state:%d in NIF: %S"), aState, &KNifName);
       
   369 		User::Leave(KErrUnknown);
       
   370 		break;
       
   371 		}
       
   372 	}
       
   373 
       
   374 void CRawIPFlow::ShutDown(TInitialisationState aState, TInt aError)
       
   375 /**
       
   376  * This method controls the shutdown sequence of the different modules
       
   377  * in the Flow. When a module completes all the shutdown tasks it will
       
   378  * call again this method with the new state.
       
   379  *
       
   380  * @param aState The current state
       
   381  * @param aError A possible error (only during initialisation)
       
   382  */
       
   383 	{
       
   384 	_LOG_L1C4(_L8("CRawIPFlow %08x:\tShutDown(aState %d, aError %d)"),
       
   385 		this, aState, aError);	
       
   386 			
       
   387 	if (aError != KErrNone)
       
   388 		{
       
   389 		// Flow is shutting down due to an error.
       
   390 		// The error code must be stored in order to call linklayer down
       
   391 		// passing that value
       
   392 		iInitError = aError;
       
   393 		}
       
   394 
       
   395 	switch (aState)
       
   396 		{
       
   397 	case MControllerObserver::EInitialised:
       
   398 		iBcaController->Stop(aError);
       
   399 		break;
       
   400 	case MControllerObserver::EBcaController:
       
   401 		LinkLayerDown(iInitError);
       
   402 		break;
       
   403 	default:
       
   404 		_LOG_L2C1(_L8("ERROR CRawIPFlow: Unknown Shutdown step"));
       
   405 		_BTT_PANIC(KNifName,KNifUnknownShutDownState);
       
   406 		break;
       
   407 		}
       
   408 	}
       
   409 
       
   410 CBinderBase* CRawIPFlow::GetBinder()
       
   411 /**
       
   412  * Returns a pointer to the Binder class
       
   413  *
       
   414  * @return a pointer to a CBinderBase derived class
       
   415  */
       
   416 	{
       
   417 	return iBinder;
       
   418 	}
       
   419 
       
   420 CBcaIoController* CRawIPFlow::GetBcaController()
       
   421 /**
       
   422  * Returns a pointer to the CBcaIoController class
       
   423  *
       
   424  * @return a pointer to CBcaIoController
       
   425  */
       
   426 	{
       
   427 	return iBcaController;
       
   428 	}
       
   429 
       
   430 void CRawIPFlow::UpdateContextState(
       
   431 	RPacketContext::TContextStatus aState, TInt /*aError*/)
       
   432 /**
       
   433  * Updates the state of the iContextState variable
       
   434  *
       
   435  * @param aState The new state
       
   436  * @param aError A possible error
       
   437  */
       
   438 	{
       
   439 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tUpdateContextState(aState %d)"), this, aState);
       
   440 
       
   441 	// Note that we do not need to close the Flow down if there's been an
       
   442 	// error, as the context state machine will do this for us.
       
   443 
       
   444 	iContextStatus = aState;
       
   445 	}
       
   446 
       
   447 // =====================================================================================
       
   448 //
       
   449 // CSubConnectionFlowBase
       
   450 //
       
   451 
       
   452 MFlowBinderControl* CRawIPFlow::DoGetBinderControlL()
       
   453 	{
       
   454 	return iBinderControl;
       
   455 	}
       
   456 
       
   457 // =====================================================================================
       
   458 //
       
   459 // MFlowBinderControl methods
       
   460 //
       
   461 
       
   462 MLowerControl* CRawIPFlow::GetControlL(const TDesC8& aProtocol)
       
   463 	{
       
   464 #ifdef __BTT_LOGGING__
       
   465 	//TBuf8<256> debugBuffer;
       
   466 	//debugBuffer.Copy(aProtocol);
       
   467 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tGetControlL(aProtocol %S)"), this, &aProtocol);
       
   468 #endif
       
   469 
       
   470 	// IPv4 and ICMP Protocols
       
   471 	if (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0)
       
   472 		{
       
   473 		if (!iBinder)
       
   474 			{
       
   475 			iBinder = new (ELeave) CIPv4Binder(*this, iTheLogger);
       
   476 #ifdef RAWIP_HEADER_APPENDED_TO_PACKETS
       
   477  			iBcaController->SetType(KIp4FrameType);
       
   478 #endif // RAWIP_HEADER_APPENDED_TO_PACKETS
       
   479 			}
       
   480 		else
       
   481 			{
       
   482 			_LOG_L1C2(_L8("CRawIPFlow %08x:\tGetControlL(): IPv4 binder already exists"), this);
       
   483 			}
       
   484 		}
       
   485 	// IPv6 Protocol
       
   486 	else if (aProtocol.CompareF(KDescIp6()) == 0)
       
   487 		{
       
   488 		if (!iBinder)
       
   489 			{
       
   490 			iBinder = new (ELeave) CIPv6Binder(*this, iTheLogger);
       
   491 #ifdef RAWIP_HEADER_APPENDED_TO_PACKETS
       
   492  			iBcaController->SetType(KIp6FrameType);
       
   493 #endif // RAWIP_HEADER_APPENDED_TO_PACKETS
       
   494 			}
       
   495 		else
       
   496 			{
       
   497 			_LOG_L1C2(_L8("CRawIPFlow %08x:\tGetControlL(): IPv6 binder already exists"), this);
       
   498 			}
       
   499 		}		
       
   500 	else
       
   501 		{
       
   502 		User::Leave(KErrNotSupported);
       
   503 		}
       
   504 
       
   505     return iBinder;
       
   506 	}
       
   507 
       
   508 MLowerDataSender* CRawIPFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
   509 /**
       
   510  * Binds upper CFProtocol to this CFProtocol
       
   511  *
       
   512  * @param aUpperReceiver A pointer to Upper layer Receive class
       
   513  * @param aUpperControl A pointer to Upper layer control class
       
   514  */
       
   515 	{
       
   516 #ifndef _DEBUG
       
   517 	(void) aProtocol;
       
   518 #endif
       
   519 
       
   520 	ASSERT (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0
       
   521 			|| aProtocol.CompareF(KDescIp6()) == 0);
       
   522 	ASSERT(iBinder);
       
   523 
       
   524     iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef());
       
   525 	return iBinder->Bind(aReceiver, aControl);
       
   526 	}
       
   527 
       
   528 void CRawIPFlow::Unbind(MUpperDataReceiver* aUpperReceiver, MUpperControl* aUpperControl)
       
   529     {
       
   530     _LOG_L1C2(_L8("CRawIPFlow %08x:\tUnbind()"), this);
       
   531 
       
   532 	ASSERT(iBinder);
       
   533 	iBinder->Unbind(aUpperReceiver, aUpperControl);
       
   534 
       
   535     delete iBinder;
       
   536     iBinder = NULL;
       
   537 
       
   538     SendDataClientIdleIfNoClients();
       
   539     }
       
   540 
       
   541 
       
   542 void CRawIPFlow::SendDataClientIdleIfNoClients()
       
   543     {
       
   544     if (iBinder == NULL)
       
   545         {
       
   546         iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
       
   547         }
       
   548     }
       
   549 
       
   550 CSubConnectionFlowBase* CRawIPFlow::Flow()
       
   551 /**
       
   552 Return the Flow corresponding to the MFlowBinderControl
       
   553 */
       
   554 	{
       
   555 	return this;
       
   556 	}
       
   557 
       
   558 // =====================================================================================
       
   559 //
       
   560 // Messages::ANode
       
   561 //
       
   562 
       
   563 void CRawIPFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   564     {
       
   565     CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
       
   566 
       
   567 	if (aMessage.IsMessage<TEBase::TError>())
       
   568 		{
       
   569 		SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue);
       
   570 		}
       
   571 	else if (TEChild::ERealmId == aMessage.MessageId().Realm())
       
   572 		{
       
   573 		switch (aMessage.MessageId().MessageId())
       
   574 			{
       
   575 		case TEChild::TDestroy::EId :
       
   576 			Destroy();
       
   577 			break;
       
   578 		default:
       
   579 //TODO - logging
       
   580 			ASSERT(EFalse);
       
   581 			}
       
   582 		}
       
   583 	else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
       
   584 		{
       
   585 		switch (aMessage.MessageId().MessageId())
       
   586 			{
       
   587 		case TCFDataClient::TStart::EId :
       
   588 			StartFlowL();
       
   589 			break;
       
   590 		case TCFDataClient::TStop::EId :
       
   591 			StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
       
   592 			break;
       
   593 		case TCFDataClient::TProvisionConfig::EId:
       
   594 			ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
       
   595 			break;
       
   596 		case TCFDataClient::TBindTo::EId:
       
   597             {
       
   598 			TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
       
   599 			if (!bindToReq.iNodeId.IsNull())
       
   600 				{
       
   601 				User::Leave(KErrNotSupported);
       
   602 				}
       
   603 			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
       
   604             }
       
   605 			break;
       
   606 		default:
       
   607 //TODO - logging
       
   608 			ASSERT(EFalse);
       
   609 			}
       
   610 		}
       
   611 	else if (TCFFlow::ERealmId == aMessage.MessageId().Realm())
       
   612 		{
       
   613 		switch (aMessage.MessageId().MessageId())
       
   614 			{
       
   615 		case TCFFlow::TBlock::EId :
       
   616 			iBlocked = ETrue;
       
   617 			break;
       
   618 		case TCFFlow::TUnBlock::EId :
       
   619 			iBlocked = EFalse;
       
   620 			if (iBinder)
       
   621 				{
       
   622 				iBinder->StartSending();
       
   623 				}
       
   624 			break;
       
   625 		case TCFFlow::TRejoin::EId:
       
   626 			{
       
   627 			TCFFlow::TRejoin& rejoinMsg = message_cast<TCFFlow::TRejoin>(aMessage);
       
   628 			TDefaultFlowFactoryQuery query(rejoinMsg.iNodeId);
       
   629 			CRawIPFlow* otherFlow = static_cast<CRawIPFlow*>(Factory().Find(query));
       
   630 			ASSERT(otherFlow);
       
   631 
       
   632 			//This rather ugly looking snipped of code implements
       
   633 			//the scenario whereat the network tears down the default
       
   634 			//scpr and the default scpr selects a new default amongst
       
   635 			//the non-default and subsequently performs a transparant
       
   636 			//swap - i.e.: the upper layer perceives this as a
       
   637 			//non-default going down. Since the datapath is pre-bound
       
   638 			//to the flow representing the default, the datapath needs
       
   639 			//to perform a transparent swap too, so that the upper layer
       
   640 			//doesn't notice anything. It does that by swapping the
       
   641 			//flows below the binders.
       
   642 			CBinderBase* localBinder = iBinder;
       
   643 			CBttLogger* logger = localBinder->iTheLogger;
       
   644 
       
   645 			TBinderControlProxy* localBinderControl = iBinderControl;
       
   646 			iBinder = otherFlow->iBinder;
       
   647 			otherFlow->iBinder->ChangeFlow(*this);
       
   648 			localBinder->ChangeFlow(*otherFlow);
       
   649 			otherFlow->iBinder = localBinder;
       
   650 			iBinderControl = otherFlow->iBinderControl;
       
   651 			otherFlow->iBinderControl = localBinderControl;
       
   652 			otherFlow->iBinderControl->iFlow = otherFlow;
       
   653 			iBinderControl->iFlow = this;
       
   654 
       
   655 			iBinder->iTheLogger = logger;
       
   656 
       
   657 			iSubConnectionProvider.Close();
       
   658 			iSubConnectionProvider.Open(address_cast<TNodeId>(rejoinMsg.iNodeId));
       
   659 			}
       
   660 			break;
       
   661 		default:
       
   662 //TODO - logging
       
   663 			ASSERT(EFalse);
       
   664 			}
       
   665 		}
       
   666 	else if (TLinkMessage::ERealmId == aMessage.MessageId().Realm())
       
   667 		{
       
   668 		switch (aMessage.MessageId().MessageId())
       
   669 			{
       
   670 		case TLinkMessage::TAgentToFlowNotification::EId:
       
   671 			{
       
   672 			TLinkMessage::TAgentToFlowNotification& msg = static_cast<TLinkMessage::TAgentToFlowNotification&>(aMessage);
       
   673 			Notification(msg.iValue);
       
   674 			break;
       
   675 			}
       
   676 		default:
       
   677 			ASSERT(EFalse);
       
   678 			}
       
   679 		}
       
   680 	else	// not a recognised realm or message
       
   681 		{
       
   682 		ASSERT(EFalse);
       
   683 		}
       
   684     }
       
   685 
       
   686 
       
   687 // =====================================================================================
       
   688 //
       
   689 // Methods for handling incoming SCPR messages
       
   690 //
       
   691 
       
   692 void CRawIPFlow::SubConnectionGoingDown()
       
   693 	{
       
   694 	}
       
   695 
       
   696 void CRawIPFlow::SubConnectionError(TInt /*aError*/)
       
   697 	{
       
   698 	}
       
   699 
       
   700 /*
       
   701 Provisioning description for RawIp CFProtocol Flow:
       
   702 
       
   703 - on receipt of the ProvisionConfig message, the pointer contained within is stored
       
   704   in iAccessPointConfig and the provisioning information contained within it is validated:
       
   705 	- CBCAProvision must be present.  It is added by the RawIpMCPr and populated from CommsDat.  A pointer to it
       
   706 	  is stored in iProvision.
       
   707   if any are missing, an error is stored in iProvisionError and sent in response to the StartFlow
       
   708   message later on (ProvisionConfig has no response).
       
   709 
       
   710 - on receipt of the StartFlow message, further provisioning information is retrieved:
       
   711 	- CIPConfig must be present.  It is added by the RawIpMCPr and populated from CommsDat.  The binder retrieves
       
   712 	  individual fields from it.
       
   713 	- CRawIpAgentConfig must be present.  It is added by the RawIpAgentHandler and populated via calls
       
   714 	  to the Agent.  A pointer to it is stored in iAgentProvision.  Note that the iGprsConfig field
       
   715 	  is a pointer to a (large) structure in the Agent (see CRawIpAgentHandler).
       
   716   if any of the above are missing, an Error message is signalled back to the SCPr in response
       
   717   to the StartFlow.
       
   718 */
       
   719 
       
   720 void CRawIPFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData)
       
   721 /**
       
   722 Handle ProvisionConfig message from SCPR.
       
   723 
       
   724 Just save the pointer for now - validate it later on StartFlow.
       
   725 
       
   726 @param aData provisioning pointer from message
       
   727 */
       
   728 	{
       
   729 	_LOG_L1C2(_L8("CRawIPFlow %08x:\tProvisionConfig()"), this);
       
   730 
       
   731 	AccessPointConfig().Close();
       
   732 	AccessPointConfig().Open(aConfigData);
       
   733 
       
   734     iProvision = static_cast<const CBCAProvision*>(AccessPointConfig().FindExtension(
       
   735         STypeId::CreateSTypeId(CBCAProvision::EUid, CBCAProvision::ETypeId)));
       
   736 
       
   737 	}
       
   738 
       
   739 void CRawIPFlow::DynamicProvisionConfigL()
       
   740 /**
       
   741 Retrieve provisioning information available only at StartFlow time.
       
   742 */
       
   743 	{
       
   744     if (iProvision == NULL)
       
   745         {
       
   746         _LOG_L1C1(_L8("CRawIPFlow:\tProvisionConfigL() - CBCAProvision config incomplete"));
       
   747 		iProvisionError = KErrCorrupt;
       
   748 		return;
       
   749         }
       
   750 
       
   751     ASSERT(iAgentProvision == NULL);
       
   752     iAgentProvision = static_cast<const CRawIpAgentConfig*>(AccessPointConfig().FindExtension(
       
   753             STypeId::CreateSTypeId(CRawIpAgentConfig::EUid, CRawIpAgentConfig::ETypeId)));
       
   754 
       
   755     if (iAgentProvision == NULL)
       
   756     	{
       
   757     	User::Leave(KErrCorrupt);
       
   758     	}
       
   759 
       
   760     const CIPConfig* wcdmaIpProvision = static_cast<const CIPConfig*>(AccessPointConfig().FindExtension(
       
   761             STypeId::CreateSTypeId(CIPConfig::EUid, CIPConfig::ETypeId)));
       
   762     if (wcdmaIpProvision == NULL)
       
   763         {
       
   764         _LOG_L1C2(_L8("CRawIPFlow %08x:\tDynamicProvisionConfigL() - WCDMA config incomplete"), this);
       
   765 		iProvisionError = KErrCorrupt;
       
   766 		return;
       
   767         }
       
   768    	// Pass pointer to binder specific provisioning information to binder
       
   769 	if (iBinder)
       
   770 		{
       
   771 		iBinder->SetProvision(*wcdmaIpProvision);
       
   772 		}
       
   773 	}
       
   774 
       
   775 
       
   776 void CRawIPFlow::Destroy()
       
   777 /**
       
   778 Handle Destroy message from SCPR.
       
   779 */
       
   780 	{
       
   781 	DeleteThisFlow();
       
   782 	}
       
   783 
       
   784 void CRawIPFlow::Notification(TInt aEvent)
       
   785 /**
       
   786 Handle Generic Link Tier messages from SCPR.
       
   787 
       
   788 These used to be implemented as Agent <-> NIF Notifications, hence the method name to promote
       
   789 some historical understanding.
       
   790 */
       
   791 	{
       
   792 	_LOG_L1C3(_L8("CRawIPFlow %08x:\tNotification(aEvent %d)"), this, aEvent);
       
   793 
       
   794 	switch (aEvent)
       
   795 	{
       
   796 	case EAgentToNifEventTypeDisableTimers: //GPRS suspension
       
   797 		{
       
   798 		_LOG_L1C1(_L8("CRawIPFlow::Received Suspend from Agent..."));
       
   799 
       
   800 		// Let the BCA controller know that data can no longer be sent over
       
   801 		// the PDP context.
       
   802 		iBcaController->UpdateContextStateFlag(EFalse);
       
   803 
       
   804 		break;
       
   805 		}
       
   806 
       
   807 	case EAgentToNifEventTypeEnableTimers: //GPRS resumption
       
   808 		{
       
   809 		_LOG_L1C1(_L8("CRawIPFlow::Received Resume from Agent..."));
       
   810 		iBcaController->UpdateContextStateFlag(ETrue);
       
   811 
       
   812 		break;
       
   813 		}
       
   814 
       
   815 	case (EAgentToNifEventTypeDisableConnection) :
       
   816 		{
       
   817 		// This is handled by NIFMAN and passed to Flow as a Stop() call
       
   818 		_LOG_L1C1(_L8("CRawIPFlow::Received Disable connection from Agent..."));
       
   819 		break;
       
   820 		}
       
   821 
       
   822 	default :
       
   823 		{
       
   824 		_LOG_L1C2(_L8("CRawIPFlow::Received Notification [%d] from Agent..."), aEvent);
       
   825 		break;
       
   826 		}
       
   827 	}//endswitch
       
   828 	}
       
   829 
       
   830 
       
   831 ESock::MLowerControl* CRawIPFlow::TBinderControlProxy::GetControlL(const TDesC8& aProtocol)
       
   832     {
       
   833     return RawIPFlow().GetControlL(aProtocol);
       
   834     }
       
   835 
       
   836 ESock::MLowerDataSender* CRawIPFlow::TBinderControlProxy::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl)
       
   837     {
       
   838     return RawIPFlow().BindL(aProtocol, aReceiver, aControl);
       
   839     }
       
   840 
       
   841 void CRawIPFlow::TBinderControlProxy::Unbind(ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl)
       
   842     {
       
   843     return RawIPFlow().Unbind(aReceiver, aControl);
       
   844     }
       
   845 
       
   846 CSubConnectionFlowBase* CRawIPFlow::TBinderControlProxy::Flow()
       
   847     {
       
   848     return iFlow;
       
   849     }
       
   850 
       
   851 // =====================================================================================
       
   852 //
       
   853 // Utility functions
       
   854 //
       
   855 
       
   856 void CRawIPFlow::PostProgressMessage(TInt aStage, TInt aError)
       
   857 	{
       
   858 	iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange( aStage, aError)).CRef());
       
   859 	}
       
   860 
       
   861 //
       
   862 // NOTE:
       
   863 // Attribute table should be in the control side module that instantiates CRawIpProvision.
       
   864 // RawIP CFProtocol does not instantiate the CRawIpProvision object, so does not need to
       
   865 // define the attribute tables.  The attribute table can therefore be placed directly into
       
   866 // the control side module.
       
   867 //
       
   868 // The reason for this is to save splitting RawIP CFProtocol into two DLL's - ECOM and Main -
       
   869 // just for control side module to link against Main DLL to retrieve the attribute table.
       
   870 // In fact, it can be placed into control side module as "START_ATTRIBUTE_TABLE" rather
       
   871 // than "EXPORT_START_ATTRIBUTE_TABLE".  In fact, do we just need "TYPEID_TABLE" ?
       
   872 //
       
   873 // EXPORT_START_ATTRIBUTE_TABLE(CRawIpProvision, KRawIpConfigUid, KRawIpConfigType)
       
   874 // END_ATTRIBUTE_TABLE()