telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/mux.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2004-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 // SPUD data multiplexer
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "mux.h"
       
    24 #include <nifmbuf.h>
       
    25 #include <in6_if.h>
       
    26 
       
    27 // Flow control constants expected by the upper protocol stack
       
    28 const TInt KStopSending		= 0;
       
    29 const TInt KContinueSending	= 1;
       
    30 
       
    31 #ifdef __FLOG_ACTIVE
       
    32 #define SPUDMUX_LOG(x) iBindMan->SpudMan()->x
       
    33 #else
       
    34 #define SPUDMUX_LOG(x)
       
    35 #endif
       
    36 
       
    37 
       
    38 //
       
    39 // CSpudMux
       
    40 //
       
    41 
       
    42 
       
    43 CSpudMux::CSpudMux(CSpudMan& aNifBase)
       
    44 	: CNifIfBase(aNifBase)
       
    45     {
       
    46 	}
       
    47 
       
    48 CSpudMux::~CSpudMux()
       
    49     {
       
    50     // Notify BindMan to delete the pointer to this object
       
    51     if (iBindMan)
       
    52     	{
       
    53 	    iBindMan->MuxClosed();
       
    54     	}
       
    55 	}
       
    56 
       
    57 /**
       
    58 Constructs the mux object
       
    59 
       
    60 @param aBindMan Reference to BindMan object
       
    61 */
       
    62 void CSpudMux::Construct(CBindMan& aBindMan)
       
    63 	{
       
    64 	iBindMan = &aBindMan;
       
    65 	
       
    66 	// Create a unique interface name
       
    67 	iIfName.Format(_L("%S[0x%08x]"), &KSpudName, this);
       
    68 	}
       
    69 
       
    70 /**
       
    71 Binds SPUD to the TCP/IP stack.
       
    72 
       
    73 @param aId Pointer to network stack object (CProtocolBase*)
       
    74 @leave KErrInUse if SPUD is already bound
       
    75 */
       
    76 void CSpudMux::BindL(TAny* aId)
       
    77 	{
       
    78 	iBindMan->SetProtocolBaseL(static_cast<CProtocolBase*>(aId));
       
    79 	}
       
    80 
       
    81 
       
    82 /**
       
    83 Fills in the info object with NIF information.
       
    84 
       
    85 @param aInfo object to hold information on return
       
    86 */
       
    87 void CSpudMux::Info(TNifIfInfo& aInfo) const
       
    88 	{
       
    89 	// Get the binder for the first (default) lower NIF.
       
    90 	CSpudBinderRef* ref = NULL;
       
    91 	TRAPD(err, ref = iBindMan->GetAnyRefL());
       
    92 	if (err == KErrNone)
       
    93 		{
       
    94 		// Read the protocol supported value from the lower NIF
       
    95 		ref->NifBase()->Info(aInfo);
       
    96 		ASSERT((aInfo.iFlags & (KNifIfIsBase | KNifIfUsesNotify | KNifIfCreatedByLink)) == (KNifIfIsBase | KNifIfUsesNotify | KNifIfCreatedByLink));
       
    97 		}
       
    98 	else
       
    99 		{
       
   100 		aInfo.iProtocolSupported=KProtocolUnknown;
       
   101 		}
       
   102 
       
   103 	// Overwrite these values with our own
       
   104 	aInfo.iName.Copy(iIfName);
       
   105 	aInfo.iVersion = TVersion(KSpudMajorVersionNumber, KSpudMinorVersionNumber, KSpudBuildVersionNumber);
       
   106 	aInfo.iFlags = KNifIfIsBase | KNifIfUsesNotify | KNifIfCreatedByLink;
       
   107 	}
       
   108 
       
   109 /**
       
   110 Takes packets from the IP stack and demultiplexes them by sending each on to
       
   111 the appropriate lower NIF for processing. The packets are assumed to be
       
   112 ordered correctly, as appropriate for the QoS guarantees given to each.
       
   113 This function's responsibility is to pass each packet to the appropriate
       
   114 lower NIF for processing, where each lower NIF handles a single PDP context.
       
   115 
       
   116 @param aPacket MBuf chain containing packet
       
   117 @param aSource Passed unchanged to lower NIF
       
   118 @return 1 for a successful send, 0 to tell upper layer to flow off
       
   119 */
       
   120 TInt CSpudMux::Send(RMBufChain& aPacket, TAny* aSource)
       
   121 	{
       
   122 	// GUQoS places the context ID for the outgoing packet into the Port field
       
   123 	// in the RMBufChain info header.
       
   124 	const RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPacket);
       
   125 	TUint contextId(info->iDstAddr.Port());
       
   126 	if (contextId >= static_cast<TUint>(KMaxPdpContexts))
       
   127 		{
       
   128 		// Context ID is illegal; use 0 instead and try to continue
       
   129 		SPUDMUX_LOG(__FLOG_1(_L("CSpudMux::Send context id %d is out of range; using 0 instead"), contextId));
       
   130 		contextId = 0;
       
   131 		}
       
   132 	const TContextId id(static_cast<TContextId>(contextId));
       
   133 
       
   134 	// Get the binder for the appropriate lower NIF.
       
   135 	CSpudBinderRef* ref = NULL;
       
   136 	TRAPD(err, ref = iBindMan->GetRefL(id));
       
   137 	if (err != KErrNone)
       
   138 		{
       
   139 		// That's odd--GUQoS is sending to an invalid context.
       
   140 		// Redirect it to the first valid context instead.
       
   141 		SPUDMUX_LOG(__FLOG_1(_L("CSpudMux::Send context id %d is invalid; searching for another"), id));
       
   142 		TRAPD(err, ref = iBindMan->GetAnyRefL());
       
   143 		if (err != KErrNone)
       
   144 			{
       
   145 			// Something is really wrong here! No contexts available at all!
       
   146 			SPUDMUX_LOG(__FLOG_0(_L("Nowhere to send data! Dropping packet")));
       
   147 			return err;
       
   148 			}
       
   149 		}
       
   150 	TInt rc = ref->NifBase()->Send(aPacket, aSource);
       
   151 
       
   152 	// See if NIF is flowing off data on this context
       
   153 	if ((rc == KStopSending) && iBindMan->SpudMan()->AreQoSEventsEnabled())
       
   154 		{
       
   155 		// Send flow off indication via GUQoS instead
       
   156 		iBindMan->SpudMan()->StopSending(id);
       
   157 		rc = KContinueSending;	// Successful send indication
       
   158 		}
       
   159 	return rc;
       
   160 	}
       
   161 
       
   162 /**
       
   163 Processes notifications from agent.
       
   164 
       
   165 @param aEvent event type
       
   166 @param aInfo data associated with event
       
   167 @return error code
       
   168 */
       
   169 TInt CSpudMux::Notification(TAgentToNifEventType aEvent, void* aInfo)
       
   170 	{
       
   171 	SPUDMUX_LOG(__FLOG_1(_L("CSpudMux::Notification received event %d"), aEvent));
       
   172 	TInt rc = KErrNotSupported;
       
   173 	switch (aEvent)
       
   174 		{
       
   175 	case EAgentToNifEventTypeModifyInitialTimer:
       
   176 	case EAgentToNifEventTypeDisableTimers:
       
   177 	case EAgentToNifEventTypeEnableTimers:
       
   178 		// Send notification to all lower NIFs
       
   179 		rc =  KErrNotReady;
       
   180 		TContextId i;
       
   181 		for (i=0; i < KMaxPdpContexts; ++i)
       
   182 			{
       
   183 			CSpudBinderRef* ref = NULL;
       
   184 			TRAP(rc, ref = iBindMan->GetRefL(i));
       
   185 			if (rc == KErrNone)
       
   186 				{
       
   187 				rc = ref->NifBase()->Notification(aEvent, aInfo);
       
   188 				}
       
   189 			}
       
   190 		break;
       
   191 
       
   192 	case EAgentToNifEventTypeDisableConnection:
       
   193 		SPUDMUX_LOG(__FLOG_0(_L("CSpudMux::Notification received EAgentToNifEventTypeDisableConnection")));
       
   194 		// TODO: How to handle this event?  Just fall through and ignore for now.
       
   195 	default:
       
   196 		break;
       
   197 		}
       
   198 
       
   199 	return rc;
       
   200 	}
       
   201 
       
   202 /**
       
   203 Returns the current state of the interface
       
   204 
       
   205 @return TIfStatus indicating the current state of the interface
       
   206 */
       
   207 TInt CSpudMux::State()
       
   208 	{
       
   209 	// Get the binder for the first (default) lower NIF.
       
   210 	CSpudBinderRef* ref = NULL;
       
   211 	TRAPD(err, ref = iBindMan->GetAnyRefL());
       
   212 	if (err != KErrNone)
       
   213 		{
       
   214 		return EIfDown;
       
   215 		}
       
   216 	
       
   217 	// Use the state of the first lower NIF as the state of the SPUD
       
   218 	return ref->NifBase()->State();
       
   219 	}
       
   220 
       
   221 /**
       
   222 Controls the NIF
       
   223 
       
   224 @param aLevel The intended level for this control option
       
   225 @param aName The name of the control option
       
   226 @param aOption Any data associated with this control option, contained within a TPckg(Buf)
       
   227 @param aSource If provided, an identifier for the source of the control option; by default, zero
       
   228 @return KErrNone if successful; otherwise one of the standard Symbian OS error codes
       
   229 */
       
   230 TInt CSpudMux::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* aSource)
       
   231 	{
       
   232 	if (aLevel==KSOLInterface)
       
   233 		{
       
   234 		switch (aName)
       
   235 			{
       
   236 		// From elsewhere
       
   237 		case KSoIfInfo:
       
   238 		case KSoIfInfo6:
       
   239 		case KSoIfConfig:
       
   240 		case KSoIfCompareAddr:
       
   241 		case KSoIfGetConnectionInfo:
       
   242 		case KSoIfHardwareAddr:
       
   243 			{
       
   244 			// Get the binder for the first (default) lower NIF.
       
   245 			CSpudBinderRef* ref = NULL;
       
   246 			TRAPD(err, ref = iBindMan->GetAnyRefL());
       
   247 			if (err != KErrNone)
       
   248 				{
       
   249 				return err;
       
   250 				}
       
   251 			return ref->NifBase()->Control(aLevel, aName, aOption, aSource);
       
   252 			}
       
   253 
       
   254 		default:
       
   255 			// Unknown event
       
   256 			// Assume it's for GUQoS, so let SpudMan handle it and error out the unknown ones
       
   257 			// These include:
       
   258 			//   KSoIfControllerPlugIn
       
   259         	//   KRegisterEventHandler
       
   260 			//   KContextSetEvents
       
   261 			//   KNifSetDefaultQoS
       
   262 			//   KContextCreate
       
   263 			//   KContextDelete
       
   264 			//   KContextActivate
       
   265 			//   KContextQoSSet
       
   266 			//   KContextTFTModify
       
   267 			//   KContextModifyActive
       
   268 			return iBindMan->SpudMan()->GuqosInput(aName, aOption);
       
   269 			}
       
   270 		}
       
   271 	return KErrNotSupported;
       
   272 	}
       
   273 
       
   274 //
       
   275 // CSpudProtocol
       
   276 //
       
   277 
       
   278 
       
   279 CSpudProtocol::CSpudProtocol()
       
   280 	{
       
   281 	}
       
   282 
       
   283 CSpudProtocol::~CSpudProtocol()
       
   284 	{
       
   285 	}
       
   286 
       
   287 /**
       
   288 Constructs the SpudProtocol object
       
   289 
       
   290 @param aBindMan reference to BindMan object
       
   291 */
       
   292 void CSpudProtocol::Construct(CBindMan& aBindMan)
       
   293 	{
       
   294 	iBindMan = &aBindMan;
       
   295 	}
       
   296 
       
   297 void CSpudProtocol::SetProtocolBaseL(CProtocolBase* aProtocolBase)
       
   298 	{
       
   299 	if(iProtocolBase)
       
   300 		{
       
   301 		SPUDMUX_LOG(__FLOG_0(_L("CSpudProtocol::SetProtocolBaseL already bound to protocol")));
       
   302 		User::Leave(KErrInUse);
       
   303 		}
       
   304 
       
   305 	iProtocolBase = aProtocolBase;
       
   306 	ASSERT(iProtocolBase);
       
   307 	}
       
   308 
       
   309 
       
   310 void CSpudProtocol::Identify(TServerProtocolDesc *aDesc) const
       
   311 	{
       
   312 	ASSERT(iProtocolBase);
       
   313     iProtocolBase->Identify(aDesc);
       
   314 	}
       
   315 
       
   316 /**
       
   317 Receives an indication that the lower NIF is ready to send packets.
       
   318 
       
   319 @param aProtocol CNifIfBase pointer of lower NIF
       
   320 */
       
   321 void CSpudProtocol::StartSending(CProtocolBase* aProtocol)
       
   322 	{
       
   323 	TContextId id = KAllContexts;
       
   324 	TRAPD(rc, id = iBindMan->FindContextIdL(reinterpret_cast<CNifIfBase*>(aProtocol)));
       
   325 	__ASSERT_ALWAYS(rc == KErrNone, iBindMan->SpudMan()->Panic());
       
   326 	iBindMan->SpudMan()->StartSending(id);
       
   327 	}
       
   328 
       
   329 /**
       
   330 Receives PDU from the lower NIF and passes it to the upper protocol layer.
       
   331 
       
   332 @param aChain Datagram to process
       
   333 @param aSourceProtocol CNifIfBase pointer of lower NIF (ignored)
       
   334 */
       
   335 void CSpudProtocol::Process(RMBufChain& aChain, CProtocolBase* /*aSourceProtocol*/)
       
   336 	{
       
   337 	ASSERT(iProtocolBase);
       
   338     iProtocolBase->Process(aChain, reinterpret_cast<CProtocolBase*>(iBindMan->SpudMux()));
       
   339 	}
       
   340 
       
   341 /**
       
   342 Receives PDU from the lower NIF and passes it to the upper protocol layer.
       
   343 
       
   344 @param aPDU Datagram to process
       
   345 @param aFrom Source address
       
   346 @param aTo Destination address
       
   347 @param aSourceProtocol (ignored)
       
   348 */
       
   349 void CSpudProtocol::Process(TDes8& aPDU, TSockAddr* aFrom, TSockAddr* aTo, CProtocolBase* /*aSourceProtocol*/)
       
   350 	{
       
   351 	ASSERT(iProtocolBase);
       
   352     iProtocolBase->Process(aPDU, aFrom, aTo, reinterpret_cast<CProtocolBase*>(iBindMan->SpudMux()));
       
   353 	}
       
   354 
       
   355 /**
       
   356 Propagates error conditions up the stack, eventually to socket service providers.
       
   357 
       
   358 @param aError The error code 
       
   359 @param aSourceProtocol (ignored)
       
   360 */
       
   361 void CSpudProtocol::Error(TInt aError, CProtocolBase* /*aSourceProtocol*/)
       
   362 	{
       
   363 	ASSERT(iProtocolBase);
       
   364     iProtocolBase->Error(aError, reinterpret_cast<CProtocolBase*>(iBindMan->SpudMux()));
       
   365 	}
       
   366 
       
   367 /**
       
   368 Calls StartSending on the upper network protocol.
       
   369 */
       
   370 void CSpudProtocol::DoStartSending() const
       
   371 	{
       
   372 	ASSERT(iProtocolBase);
       
   373 	iProtocolBase->StartSending(reinterpret_cast<CProtocolBase*>(iBindMan->SpudMux()));
       
   374 	}
       
   375