datacommsserver/esockserver/ssock/ss_sapshim.cpp
changeset 0 dfb7c4ff071f
child 2 dee179edb159
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-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 //
       
    15 
       
    16 /**
       
    17  @file SS_SAPSHIM.CPP
       
    18 */
       
    19 
       
    20 #define SYMBIAN_NETWORKING_UPS
       
    21 #include "ss_sapshim.h"
       
    22 
       
    23 #include <ss_std.h>
       
    24 #include <ss_glob.h>
       
    25 #include <comms-infras/ss_roles.h>
       
    26 #include <comms-infras/ss_log.h>
       
    27 #include <comms-infras/ss_subconnprov.h>
       
    28 #include <comms-infras/ss_connprov.h>
       
    29 #include <ss_protprov.h>
       
    30 #include <ss_sock.h>
       
    31 #include <comms-infras/ss_protflow.h>
       
    32 #include <in_sock.h> // KAfInet
       
    33 #include <elements/nm_messages_child.h>
       
    34 #include <elements/nm_messages_peer.h>
       
    35 
       
    36 #include <comms-infras/nifif.h>
       
    37 #include <comms-infras/nifif_internal.h>
       
    38 
       
    39 #include <addressupdate.h>
       
    40 
       
    41 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    42 #include <comms-infras/ss_nodemessages_flow.h>
       
    43 #include <comms-infras/ss_nodemessages_ipmessages.h>
       
    44 #include <comms-infras/ss_nodemessages_internal_esock.h>
       
    45 
       
    46 #include "ss_protopt.h"
       
    47 
       
    48 #ifdef SYMBIAN_NETWORKING_UPS
       
    49 #include <comms-infras/ss_upsaccesspointconfigext.h>
       
    50 #include <comms-infras/upsmessages.h>
       
    51 
       
    52 
       
    53 #ifdef _DEBUG
       
    54 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    55 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    56 _LIT(KSpecAssert_ESockSSocksspshm, "ESockSSocksspshm");
       
    57 #endif
       
    58 
       
    59 _LIT_SECURITY_POLICY_C1(KPolicyNetworkServices, ECapabilityNetworkServices);
       
    60 #endif
       
    61 
       
    62 using namespace ESock;
       
    63 using namespace Messages;
       
    64 using namespace MeshMachine;
       
    65 using namespace Factories;
       
    66 
       
    67 //CHostResolver specific functions this is to remove once we have app layer protocols
       
    68 //***************************************************************************************
       
    69 //also loo for iHostResolverNotify
       
    70 MLowerControl* CTransportFlowShim::GetControlL(const TDesC8& /*aProtocol*/)
       
    71     {
       
    72     return this;
       
    73     }
       
    74 
       
    75 TInt CTransportFlowShim::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
    76     {
       
    77     return iLowerControl ? iLowerControl->Control(aLevel, aName, aOption) : KErrNotReady;
       
    78     }
       
    79 
       
    80 MLowerDataSender* CTransportFlowShim::BindL(const TDesC8& /*aProtocol*/, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
    81     {
       
    82     if (aReceiver || iProvider || IsBoundToSession())
       
    83         {
       
    84         User::Leave(KErrInUse);
       
    85         }
       
    86     iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef());
       
    87     iHostResolverNotify = aControl;
       
    88     return this;
       
    89     }
       
    90 
       
    91 void CTransportFlowShim::Unbind( MUpperDataReceiver* /*aReceiver*/, MUpperControl* aControl)
       
    92     {
       
    93     (void)aControl;
       
    94     __ASSERT_DEBUG(aControl == iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 1));
       
    95     __ASSERT_DEBUG(iDCIdle <= EClientsPresent, User::Panic(KSpecAssert_ESockSSocksspshm, 2));
       
    96     iDCIdle = EIdle;
       
    97     iHostResolverNotify = NULL;
       
    98     if(iSubConnectionProvider.IsOpen())	// legacy flows have no control side
       
    99     	{
       
   100     	ProcessDCIdleState();
       
   101     	}
       
   102     }
       
   103 
       
   104 MLowerDataSender::TSendResult CTransportFlowShim::Send(RMBufChain& /*aData*/)
       
   105     {
       
   106     __ASSERT_DEBUG(iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 3));
       
   107 
       
   108     TBuf8<sizeof(TConnectionInfo)> buf;
       
   109     if (Control(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), buf) == KErrNone)
       
   110         {
       
   111         iHostResolverNotify->StartSending();
       
   112         }
       
   113     else if (!iLowerControl)
       
   114         {
       
   115 #ifdef SYMBIAN_NETWORKING_UPS
       
   116 		TInt result = SetupForNoBearerOnSend();
       
   117 		if (result != KErrNone)
       
   118 			{
       
   119 			return TSendResult(result);
       
   120 			}
       
   121 #endif
       
   122 		__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 4));	// legacy flows have no control side, so must never get here
       
   123         PostNoBearer();
       
   124         }
       
   125 
       
   126     return MLowerDataSender::ESendAccepted;
       
   127     }
       
   128 //***************************************************************************************
       
   129 //End of CHostResolver specific functions also look for iHostResolverNotify to find the rest
       
   130 
       
   131 #ifndef SYMBIAN_NETWORKING_UPS
       
   132 
       
   133 //
       
   134 // Not used with UPS support - CUpsTransportFlowShim::NewL() used instead.
       
   135 //
       
   136 
       
   137 CTransportFlowShim* CTransportFlowShim::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf)
       
   138 	{
       
   139 	return new (ELeave) CTransportFlowShim(aFactory, aSubConn, aProtocolIntf);
       
   140 	}
       
   141 
       
   142 #endif
       
   143 
       
   144 CTransportFlowShim::CTransportFlowShim(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf)
       
   145 : CNetworkFlow(aFactory, aSubConn, aProtocolIntf), iFlowParams(TFlowParams(NULL, NULL, KUndefinedProtocol, NULL, NULL))
       
   146 	{
       
   147     LOG_NODE_CREATE(KESockFlowTag, CTransportFlowShim)
       
   148 	}
       
   149 
       
   150 
       
   151 void CTransportFlowShim::SetSSP(CServProviderBase& aSSP)
       
   152 	{
       
   153 	__ASSERT_DEBUG(iProvider == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 5));
       
   154 	iProvider = &aSSP;
       
   155 	iProvider->SetNotify(this);
       
   156 	}
       
   157 
       
   158 CTransportFlowShim::~CTransportFlowShim()
       
   159 	{
       
   160 	// Remove ourselves from any listening control session's accept queue.
       
   161 	if(iListenerControlNotify)
       
   162 		{
       
   163 		iListenerControlNotify->DisconnectFromListener(*this);
       
   164 		}
       
   165 
       
   166 	if(!iDetaching)
       
   167 		{
       
   168 		delete iProvider;
       
   169 		iProvider = NULL;
       
   170 		}
       
   171 
       
   172 	Messages::TEBase::TError err(TEBase::TNull::Id(), KErrBindersInvalid);
       
   173     SubConnectionError(err, EErrorAllOperations);
       
   174 
       
   175     LOG_NODE_DESTROY(KESockFlowTag, CTransportFlowShim)
       
   176 	}
       
   177 
       
   178 void CTransportFlowShim::SetSockType(TUint aSockType)
       
   179 	{
       
   180 	if (iProvider)
       
   181 		{
       
   182 		iProvider->SetSockType(aSockType);
       
   183 		}
       
   184 	}
       
   185 
       
   186 MSessionControl* CTransportFlowShim::GetControlL(TInt aSessionType,MSessionControlNotify& aSessionControlNotify)
       
   187     {
       
   188     CNetworkFlow::GetControlL(aSessionType,aSessionControlNotify);
       
   189     SetSockType(aSessionType);
       
   190 	return this;
       
   191     }
       
   192 
       
   193 MSessionData* CTransportFlowShim::BindL(MSessionDataNotify& aNotify)
       
   194     {
       
   195 	LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tBindL(aNotify 0x%08x)"), this, &aNotify) );
       
   196 
       
   197 	// The flow shim now manages custody and loading of the protocol involved.
       
   198 	// However in the case of host resolvers, until ported for the same behaviour, protocol loading is still managed by the socket.
       
   199 	if(iFlowParams.iFlowLoadsProtocol)
       
   200 		{
       
   201 		CProtocolRef * protocolReference = ProtocolManager::FindProtocolL(
       
   202 			iFlowParams.iAddrFamily,
       
   203 			iFlowParams.iSocketType,
       
   204 			iFlowParams.iProtocol);
       
   205 
       
   206         if (protocolReference->GetFlag() & CProtocolRef::EThreePlaneCommsBased)
       
   207             {
       
   208             // Three plane comms protos should not be seen here. If an RSocket is opened with a supported
       
   209             // protocol and it happens to be 3PC this point will be reached. In the case of RTP some
       
   210             // special processing is performed (in the SCPR) in order to sort out the mess and ensure that
       
   211             // a UDP/TCP flow is requested instead.
       
   212             User::Leave(KErrProtocolNotReady);
       
   213             }
       
   214 
       
   215         // Check if the protocol is supported over sockets
       
   216         if (!(protocolReference->Info().iServiceTypeInfo & ESocketSupport))
       
   217             {
       
   218             User::Leave(KErrNotSupported);
       
   219             }
       
   220 
       
   221         // Have the protocol loaded if not already the case and confirm it has socket support
       
   222         protocolReference->LoadAndBindL();
       
   223 
       
   224         __ASSERT_DEBUG(iProtocolReference == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 6));
       
   225         iProtocolReference = protocolReference;
       
   226 
       
   227         // Have the protocol added to the list of protocols for the session it is associated with
       
   228         CSockSessionProxy* sessionProxy = reinterpret_cast<CSockSessionProxy*>(iFlowParams.iSessionProxy);
       
   229         if(sessionProxy != NULL)
       
   230             {
       
   231             sessionProxy->AddProtocolL(iProtocolReference->Protocol());
       
   232             }
       
   233 
       
   234         // Fetch a new SAP from the protocol for this flow
       
   235         if (iProvider == NULL)
       
   236             {
       
   237             iProvider = iProtocolReference->Protocol()->NewSAPL(iFlowParams.iSocketType);
       
   238 
       
   239 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   240             // Set the options iterating the RArray variable
       
   241             SetProtocolOptions();
       
   242 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   243     
       
   244             if (iProvider)
       
   245                 {
       
   246                 iProvider->SetNotify(this);
       
   247                 }
       
   248             }
       
   249 		}
       
   250     
       
   251     // Now perform the binding proper
       
   252     if (!iProvider)
       
   253         {
       
   254         User::Leave(KErrNotSupported);
       
   255         }
       
   256         
       
   257     __ASSERT_DEBUG(!iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 8));
       
   258     CNetworkFlow::BindL(aNotify);
       
   259     iProvider->SetNotify(this);
       
   260 
       
   261 	return this;
       
   262     }
       
   263 
       
   264 void CTransportFlowShim::Unbind()
       
   265     {
       
   266 	LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tUnbind()"), this) );
       
   267 
       
   268 	// Infant mortality case in which binding never completed,
       
   269 	if(iFlowParams.iProtocol == KUndefinedProtocol)
       
   270 		{
       
   271 		delete this;
       
   272 		return;
       
   273 		}
       
   274 
       
   275 	// Legacy support for host resolvers
       
   276 	if(iHostResolverNotify)
       
   277 		{
       
   278 		__ASSERT_DEBUG(!iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 9));	// can't have both HR & SAP
       
   279 
       
   280 		LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tUnbind(): iBearerExpected %d"), this, iBearerExpected) );
       
   281 		if (!iBearerExpected)
       
   282 			{
       
   283 			delete this;
       
   284 			}
       
   285 		else
       
   286 			{
       
   287 			iDeleteUponBearerReception = ETrue;
       
   288 			iHostResolverNotify = NULL;
       
   289 			}
       
   290 		return;
       
   291 		}
       
   292 
       
   293 	if (iProvider)
       
   294 		{
       
   295 		iProvider->SetNotify(NULL);
       
   296 
       
   297 		if (!iDetaching)
       
   298 			{
       
   299 			delete iProvider;
       
   300 			iProvider = NULL;
       
   301 			}
       
   302 		}
       
   303 
       
   304 #ifdef SYMBIAN_NETWORKING_UPS
       
   305 	// Hook for derived classes to do cleanup before unbind occurs
       
   306 	PreUnbind();
       
   307 #endif
       
   308 
       
   309 	CNetworkFlow::Unbind();
       
   310     }
       
   311 
       
   312 ESock::CSubConnectionFlowBase& CTransportFlowShim::CloneFlowL()
       
   313     {
       
   314     __ASSERT_DEBUG(iProtocolIntf, User::Panic(KSpecAssert_ESockSSocksspshm, 10));
       
   315     TDefaultFlowFactoryQuery query (iProtocolIntf->ControlProviderId(), iSubConnectionProvider.RecipientId());
       
   316 	ESock::CSubConnectionFlowBase& flow = static_cast<ESock::CSubConnectionFlowBase&>(*(Factory().CreateObjectL(query)));
       
   317 	// Legacy flows lack a control provider
       
   318 	if(iSubConnectionProvider.IsOpen())
       
   319 		{
       
   320 		TCFPeer::TJoinRequest msg(flow.Id(), TClientType(TCFClientType::EData, TCFClientType::EActive));
       
   321 		iSubConnectionProvider.PostMessage(Id(), msg);
       
   322 		}
       
   323 	return flow;
       
   324     }
       
   325 
       
   326 void CTransportFlowShim::Start()
       
   327 	/**
       
   328 	Start a service provider.
       
   329 	*/
       
   330 	{
       
   331 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 11));
       
   332 	iProvider->Start();
       
   333 	}
       
   334 
       
   335 void CTransportFlowShim::LocalName(TSockAddr& anAddr) const
       
   336 /** Gets the local name (address) of the socket service provider entity. The format
       
   337 of the data in the TSockAddr object is defined by individual protocols.
       
   338 
       
   339 The local address is the address of the local machine plus a local port number.
       
   340 Generally only the port number is important, unless you have two IP interfaces,
       
   341 for example.
       
   342 
       
   343 @param anAddr The address to be filled in */
       
   344 	{
       
   345 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 12));
       
   346 	iProvider->LocalName(anAddr);
       
   347 	}
       
   348 
       
   349 void CTransportFlowShim::SetLocalName(TSockAddr& anAddr)
       
   350 /** Sets the local name (address) of the socket service provider entity. The format
       
   351 of the data in the TSockAddr object is defined by individual protocols.
       
   352 
       
   353 @param anAddr The address */
       
   354 	{
       
   355 	CNetworkFlow::SetLocalName(anAddr);
       
   356 	PostDataClientRouted();
       
   357 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 65));
       
   358 	TInt err = iProvider->SetLocalName(anAddr);
       
   359 	if (err != KErrNone)
       
   360 		{
       
   361 		// Post TError to self, which will result in SubConnectionError to
       
   362 		// be called in the TError handling. Have to fake that the message is
       
   363 		// coming from iSubConnectionProvider otherwise ReceivedL will leave.
       
   364 		RClientInterface::OpenPostMessageClose(iSubConnectionProvider.RecipientId(), Id(), TEBase::TError(err).CRef());
       
   365 		return;
       
   366 		}
       
   367 
       
   368 	SetLocalNameProcess();
       
   369 	}
       
   370 
       
   371 void CTransportFlowShim::SetLocalNameProcess()
       
   372 	{
       
   373 	TBool bearerSent = EFalse;
       
   374 	if(iFlowParams.iFlowRequestType != TFlowParams::EImplicit)
       
   375 		{
       
   376 		// For explicit sockets, TNoBearer will be sent out if it has not already
       
   377 		// been done so. This was introduced for PREQ2279, as it is necessary
       
   378 		// to lock this SAP to an interface for incoming sockets. Once locked,
       
   379 		// this ensures that any incoming packets are only accepted over the locked down
       
   380 		// interface and no other interfaces. To lock the interface down the
       
   381 		// NoBearer sequence is executed. This change will also now apply to
       
   382 		// outgoing explicit sockets. The change for outgoing explicit sockets is
       
   383 		// that the NoBearer sequence is started here instead of when receiving
       
   384 		// a NoBearer upcall from the protocol.
       
   385 
       
   386 		// Attempt to send out TNoBearer.
       
   387 		if (DoNoBearer())
       
   388 		    {
       
   389 		    // TNoBearer was sent out.
       
   390 			bearerSent = ETrue;
       
   391 		    }
       
   392 		}
       
   393 
       
   394 	if (!bearerSent)
       
   395 		{
       
   396 		// No Bearer was already sent out earlier, or this is an implicit socket.
       
   397 		iSessionControlNotify->SetLocalNameComplete();
       
   398 		}
       
   399 	}
       
   400 
       
   401 
       
   402 TBool CTransportFlowShim::DoNoBearer()
       
   403 /**
       
   404 Do the actual no Bearer call.
       
   405 @return ETrue if the NoBearer post was actually done, EFalse otherwise
       
   406 */
       
   407 	{
       
   408 	TInt ret = EFalse;
       
   409 	if(!iIsStopped)
       
   410 		{ // Prevent sending NoBearer if DataClientStop was received
       
   411 		if (LockToConnectionInfo() != KErrNone)
       
   412 		    {
       
   413 	        __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 66));
       
   414 			PostNoBearer();
       
   415 			ret = ETrue;
       
   416 		    }
       
   417 		iUseBearerErrors = EFalse;
       
   418 		ClearDataClientRoutedGuard();
       
   419 		}
       
   420 	return ret;
       
   421 	}
       
   422 
       
   423 
       
   424 
       
   425 void CTransportFlowShim::RemName(TSockAddr& anAddr) const
       
   426 /** Gets the remote name (address) of the socket service provider entity. The format
       
   427 of the data in the TSockAddr object is defined by individual protocols.
       
   428 
       
   429 A remote address is either the address you're sending data to (non connection-oriented
       
   430 sockets)* or the remote end of the connection. It is the address of the remote
       
   431 machine (your peer in the network) plus a port number.
       
   432 
       
   433 @note RemName is only meaningful if the socket server client has called Connect()
       
   434 to set up a default address for SendTo(). This function will only be called
       
   435 on the protocol if this is the case.
       
   436 
       
   437 @param anAddr The address to be filled in */
       
   438 	{
       
   439 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 14));
       
   440 	iProvider->RemName(anAddr);
       
   441 	}
       
   442 
       
   443 TInt CTransportFlowShim::SetRemName(TSockAddr& anAddr)
       
   444 /** Sets the remote name (address) of the socket service provider entity. The format
       
   445 of the data in the TSockAddr object is defined by individual protocols.
       
   446 
       
   447 @param anAddr The address
       
   448 @return Returns KErrNone if the remote name is correctly set or, if this is
       
   449 not the case, an informative error number. */
       
   450 	{
       
   451 	CNetworkFlow::SetRemName(anAddr);
       
   452 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 15));
       
   453 	return iProvider->SetRemName(anAddr);
       
   454 	}
       
   455 
       
   456 TInt CTransportFlowShim::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const
       
   457 /** Gets some protocol specific option when called by the socket server on behalf of a
       
   458 client. A protocol may pass the request down a protocol	stack (to protocols it is bound
       
   459 to) using the GetOption() function of CProtocolBase.
       
   460 
       
   461 @param aLevel Option level.
       
   462 @param aName Option name.
       
   463 @param anOption Option data.
       
   464 @return System wide error code.
       
   465 */
       
   466 	{
       
   467 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 16));
       
   468 	return iProvider->GetOption(aLevel, aName, anOption);
       
   469 	}
       
   470 
       
   471 void CTransportFlowShim::Ioctl(TUint aLevel, TUint aName, TDes8* anOption)
       
   472 /** Performs some protocol specific IO control.
       
   473 
       
   474 @note If this function is called erroneously, the protocol should call Error() on the
       
   475 socket. If an Ioctl call is already outstanding, the client will be panicked with the
       
   476 value ETwoIoctls.
       
   477 
       
   478 @param aLevel Option level.
       
   479 @param aName Option name.
       
   480 @param anOption Option data.
       
   481 */
       
   482 	{
       
   483 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 17));
       
   484 	iProvider->Ioctl(aLevel, aName, anOption);
       
   485 	}
       
   486 
       
   487 void CTransportFlowShim::CancelIoctl(TUint aLevel, TUint aName)
       
   488 /** Cancels an outstanding Ioctl call. You are guaranteed only to have one outstanding
       
   489 at once.
       
   490 
       
   491 @param aLevel IOCTL level.
       
   492 @param aName IOCTL name.
       
   493 */
       
   494 	{
       
   495 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 18));
       
   496 	iProvider->CancelIoctl(aLevel, aName);
       
   497 	}
       
   498 
       
   499 TInt CTransportFlowShim::SetOption(TUint aLevel, TUint aName, const TDesC8 &anOption)
       
   500 /** Sets some protocol specific option when called by the socket server on behalf of a
       
   501 client. A protocol may pass the request down a protocol	stack (to protocols it is bound
       
   502 to) using the SetOption() function	of CProtocolBase.
       
   503 
       
   504 @param aLevel Option level.
       
   505 @param aName Option name.
       
   506 @param anOption Option data.
       
   507 @return System wide error code.
       
   508 */
       
   509 	{
       
   510 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 19));
       
   511 	return iProvider->SetOption(aLevel, aName, anOption);
       
   512 	}
       
   513 
       
   514 void CTransportFlowShim::ActiveOpen()
       
   515 /** Initiates a connection operation - this means that it tells the protocol to
       
   516 attempt to connect to a peer. It is called by the socket server in response
       
   517 to a connect request from a client.
       
   518 
       
   519 This version of the function has user data in the connection frame.
       
   520 
       
   521 Only ever called on connection-oriented sockets. Such a socket
       
   522 should always have both the local address and the remote address specified
       
   523 before this function is called. If this is not the case then the protocol
       
   524 should panic.
       
   525 
       
   526 When a connection has completed, the protocol should call ConnectComplete()
       
   527 on its TNotify. If an error occurs during connection the protocol should not
       
   528 call ConnectComplete() at all; instead it should call Error().
       
   529 */
       
   530 	{
       
   531 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 20));
       
   532 	iProvider->ActiveOpen();
       
   533 	}
       
   534 
       
   535 void CTransportFlowShim::ActiveOpen(const TDesC8& aConnectionData)
       
   536 /** Initiates a connection operation - this means that it tells the protocol to
       
   537 attempt to connect to a peer. It is called by the socket server in response
       
   538 to a connect request from a client.
       
   539 
       
   540 This version of the function has user data in the connection frame.
       
   541 
       
   542 Only ever called on connection-oriented sockets. Such a socket
       
   543 should always have both the local address and the remote address specified
       
   544 before this function is called. If this is not the case then the protocol
       
   545 should panic.
       
   546 
       
   547 When a connection has completed, the protocol should call ConnectComplete()
       
   548 on its TNotify. If an error occurs during connection the protocol should not
       
   549 call ConnectComplete() at all; instead it should call Error().
       
   550 
       
   551 @param aConnectionData If the protocol supports user specified connection
       
   552 data, then it will be held in this buffer. */
       
   553 	{
       
   554 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 21));
       
   555 	iProvider->ActiveOpen(aConnectionData);
       
   556 	}
       
   557 
       
   558 TInt CTransportFlowShim::PassiveOpen(TUint aQueueSize)
       
   559 /** Tells the protocol to start waiting for an incoming connection request on this
       
   560 socket (i.e. port). It is called by the socket server in response to a listen
       
   561 request from a client.
       
   562 
       
   563 Only ever called on connection-oriented sockets. Such a socket
       
   564 should always have both the local address and the remote address specified
       
   565 before this function is called. If this is not the case, then the protocol
       
   566 should panic.
       
   567 
       
   568 The aQue parameter is the number of sockets which can be waiting for an outstanding
       
   569 Start after calling ConnectComplete(). The protocol should keep a count of
       
   570 sockets in this state - incrementing a variable in ConnectComplete(), and
       
   571 decrementing it in Start().
       
   572 
       
   573 When a connection has completed, the protocol should call ConnectComplete()
       
   574 on its TNotify. If an error occurs during connection the protocol should not
       
   575 call ConnectComplete() at all; instead it should call Error().
       
   576 
       
   577 @param aQueSize Size of connect queue.
       
   578 */
       
   579 	{
       
   580 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 22));
       
   581 	return iProvider->PassiveOpen(aQueueSize);
       
   582 	}
       
   583 
       
   584 TInt CTransportFlowShim::PassiveOpen(TUint aQueueSize, const TDesC8& aConnectionData)
       
   585 /** Tells the protocol to start waiting for an incoming connection request on this
       
   586 socket (i.e. port). It is called by the socket server in response to a listen
       
   587 request from a client.
       
   588 
       
   589 This version of the function has user data in the connection frame.
       
   590 
       
   591 Only ever called on connection-oriented sockets. Such a socket
       
   592 should always have both the local address and the remote address specified
       
   593 before this function is called. If this is not the case then the protocol
       
   594 should panic.
       
   595 
       
   596 The aQue parameter is the number of sockets which can be waiting for an outstanding
       
   597 Start after calling ConnectComplete(). The protocol should keep a count of
       
   598 sockets in this state - incrementing a variable in ConnectComplete(), and
       
   599 decrementing it in Start().
       
   600 
       
   601 When a connection has completed the protocol should call ConnectComplete()
       
   602 on its TNotify. If an error occurs during connection the protocol should not
       
   603 call ConnectComplete() at all; instead it should call Error().
       
   604 
       
   605 @param aQueueSize size of connect queue
       
   606 @param aConnectionData if the protocol supports user specified connection data
       
   607 then it will be held in this buffer. */
       
   608 	{
       
   609 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 23));
       
   610 	return iProvider->PassiveOpen(aQueueSize, aConnectionData);
       
   611 	}
       
   612 
       
   613 void CTransportFlowShim::Shutdown(MSessionControl::TCloseType aOption)
       
   614 /** Terminates a connection (or closes a non connection-oriented socket down).
       
   615 
       
   616 The value of the option argument specifies the type of processing which will
       
   617 be required of the protocol after this function is called.
       
   618 
       
   619 Normally, when the socket server has called Shutdown() for a socket, it will
       
   620 wait for the socket to call CanClose() before destroying the CServProviderBase
       
   621 object. However, if the option argument is EImmediate, the CServProviderBase
       
   622 will be destroyed as soon as Shutdown() returns.
       
   623 
       
   624 @param option The shutdown type. */
       
   625 	{
       
   626 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 24));
       
   627 	if (aOption == MSessionControl::EImmediate)
       
   628 		{
       
   629 		iShuttingDown = ETrue;
       
   630 		}
       
   631 
       
   632 	// It is possible for the provider to be null if an error occurs immediatly
       
   633 	// after socket creation before the flow is bound and the provider is received
       
   634 	// from the protocol.
       
   635 	if(iProvider)
       
   636 		{
       
   637 		iProvider->Shutdown(CServProviderBase::TCloseType(aOption));
       
   638 		}
       
   639 	}
       
   640 
       
   641 void CTransportFlowShim::Shutdown(MSessionControl::TCloseType aOption, const TDesC8& aDisconnectionData)
       
   642 /** Terminates a connection (or closes a non connection-oriented socket down).
       
   643 
       
   644 The value of the option argument specifies the type of processing which will
       
   645 be required of the protocol after this function is called.
       
   646 
       
   647 Normally, when the socket server has called Shutdown() for a socket, it will
       
   648 wait for the socket to call CanClose() before destroying the CServProviderBase
       
   649 object. However, if the option argument is EImmediate, the CServProviderBase
       
   650 will be destroyed as soon as Shutdown() returns.
       
   651 
       
   652 @param option The shutdown type.
       
   653 @param aDisconnectionData If the protocol supports disconnect data, any such
       
   654 data required will be held in this buffer. */
       
   655 	{
       
   656 	// It is possible for the provider to be null if an error occurs immediatly
       
   657 	// after socket creation before the flow is bound and the provider is received
       
   658 	// from the protocol.
       
   659 	if(iProvider)
       
   660 		{
       
   661 		iProvider->Shutdown(CServProviderBase::TCloseType(aOption), aDisconnectionData);
       
   662 		}
       
   663 	}
       
   664 
       
   665 void CTransportFlowShim::AutoBind()
       
   666 /** Specifies that the protocol should choose a local address for the service access
       
   667 point itself. */
       
   668 	{
       
   669 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 25));
       
   670 	iProvider->AutoBind();
       
   671 	SetLocalNameProcess();
       
   672 
       
   673 	}
       
   674 
       
   675 TUint CTransportFlowShim::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* anAddr)
       
   676 /** Sends data onto the network via the protocol.
       
   677 
       
   678 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has
       
   679 been called on their MSocketNotify before Write() is called).
       
   680 
       
   681 The socket server keeps track of how much data is waiting and then tries to send it all
       
   682 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than
       
   683 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it
       
   684 is ready to send more data.
       
   685 
       
   686 anAddr is the address to write the data to.	Connection oriented sockets always use the
       
   687 default value.
       
   688 
       
   689 @param aDesc The data to be sent.
       
   690 @param aOptions Protocol specific options.
       
   691 @param anAddr Address to write the data to.
       
   692 
       
   693 @returns For stream-oriented protocols the return value is the number of bytes actually written.
       
   694 If this is less than the length of the descriptor then the protocol should call CanSend()
       
   695 when it is ready to send more data. For datagram-oriented protocols, the write should return
       
   696 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds -
       
   697 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is
       
   698 ready to send more data. If the Write() fails due to some error, then it should call Error() with
       
   699 an informative error number.
       
   700 */
       
   701 	{
       
   702 	CNetworkFlow::Write( aDesc, aOptions, anAddr);
       
   703 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 26));
       
   704 	return iProvider->Write(aDesc, aOptions, anAddr);
       
   705 	}
       
   706 
       
   707 TInt CTransportFlowShim::Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr)
       
   708 /** Sends data onto the network via the protocol.
       
   709 
       
   710 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has
       
   711 been called on their MSocketNotify before Write() is called).
       
   712 
       
   713 The socket server keeps track of how much data is waiting and then tries to send it all
       
   714 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than
       
   715 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it
       
   716 is ready to send more data.
       
   717 
       
   718 anAddr is the address to write the data to.	Connection oriented sockets always use the
       
   719 default value.
       
   720 
       
   721 @param aData The data to be sent.
       
   722 @param aOptions Protocol specific options.
       
   723 @param anAddr Address to write the data to.
       
   724 
       
   725 @returns For stream-oriented protocols the return value is the number of bytes actually written.
       
   726 If this is less than the length of the descriptor then the protocol should call CanSend()
       
   727 when it is ready to send more data. For datagram-oriented protocols, the write should return
       
   728 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds -
       
   729 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is
       
   730 ready to send more data. If the Write() fails due to some error, then it should call Error() with
       
   731 an informative error number.
       
   732 */
       
   733 	{
       
   734 	CNetworkFlow::Write(aData, aOptions, anAddr);
       
   735 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 27));
       
   736 	return iProvider->Write(aData, aOptions, anAddr);
       
   737 	}
       
   738 
       
   739 void CTransportFlowShim::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* anAddr)
       
   740 /** Gets data which the protocol has indicated is waiting in its buffers using the NewData
       
   741 up-call on the MSocketNotify.
       
   742 
       
   743 GetData() will only ever be called for as much data as the protocol has specified it can process
       
   744 using the NewData up-call.
       
   745 
       
   746 For stream oriented protocols GetData() should fill the descriptor with data from the stream. On
       
   747 a datagram protocol GetData() should copy one datagram into the descriptor and set the length of
       
   748 the descriptor. If a full datagram will not fit into the supplied descriptor, the overflow should
       
   749 be discarded.
       
   750 
       
   751 anAddr should be filled in by the protocol with the address of where the data came from.
       
   752 
       
   753 @param aDesc  The buffer for data.
       
   754 @param aOptions Protocol specific options.
       
   755 @param anAddr Address where the data came from.
       
   756 */
       
   757 	{
       
   758 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 28));
       
   759 	iProvider->GetData(aDesc, aOptions, anAddr);
       
   760 	}
       
   761 
       
   762 TInt CTransportFlowShim::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr)
       
   763 /** Gets data which the protocol has indicated is waiting in its buffers using the NewData
       
   764 up-call on the MSocketNotify.
       
   765 
       
   766 GetData() will only ever be called for as much data as the protocol has specified it can process
       
   767 using the NewData up-call.
       
   768 
       
   769 For stream oriented protocols GetData() should fill the descriptor with data from the stream. On
       
   770 a datagram protocol GetData() should copy one datagram into the descriptor and set the length of
       
   771 the descriptor. If a full datagram will not fit into the supplied descriptor, the overflow should
       
   772 be discarded.
       
   773 
       
   774 anAddr should be filled in by the protocol with the address of where the data came from.
       
   775 
       
   776 @param aDesc  The buffer for data.
       
   777 @param aOptions Protocol specific options.
       
   778 @param anAddr Address where the data came from.
       
   779 */
       
   780 	{
       
   781 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 29));
       
   782 	return iProvider->GetData(aData, aLength, aOptions, anAddr);
       
   783 	}
       
   784 
       
   785 TInt CTransportFlowShim::SecurityCheck(MProvdSecurityChecker* aChecker)
       
   786 /**
       
   787 Ask the SAP provider to perform a security policy check on the client process (default implementation).
       
   788 */
       
   789 	{
       
   790 	// ********************************************************************
       
   791 	// NOTE: KErrNone for now, but this should be changed to KErrNotSupported to
       
   792 	// turn on strict checking and fail PRTs that have not been secured.
       
   793 	// ********************************************************************
       
   794 
       
   795 	__ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 30));
       
   796 	return iProvider->SecurityCheck(aChecker);
       
   797 	}
       
   798 
       
   799 void CTransportFlowShim::NewData(TUint aCount)
       
   800 	{
       
   801 	__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 31));
       
   802 	iSessionDataNotify->NewData(aCount);
       
   803 	}
       
   804 
       
   805 void CTransportFlowShim::CanSend()
       
   806 	{
       
   807 	__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 32));
       
   808 	iSessionDataNotify->CanSend();
       
   809 	}
       
   810 
       
   811 void CTransportFlowShim::ConnectComplete()
       
   812 	{
       
   813 	__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 33));
       
   814 	iSessionControlNotify->ConnectComplete();
       
   815 	}
       
   816 
       
   817 void CTransportFlowShim::ConnectComplete(const TDesC8& aConnectData)
       
   818 	{
       
   819 	__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 34));
       
   820 	iSessionControlNotify->ConnectComplete(aConnectData);
       
   821 	}
       
   822 
       
   823 CTransportFlowShim* CTransportFlowShim::CloneNSetSAP(CServProviderBase& aSSP)
       
   824     {
       
   825 	//Here we can afford to create a flow directly since we know sub-connection
       
   826 	//+ protocols & flow plug-is've been already loaded while opening listenning socket
       
   827 	//this is the only case when flow joins without being created from control side
       
   828 	CTransportFlowShim* shimFlow = NULL;
       
   829 	TRAPD(ret,shimFlow = factoryobject_cast<CTransportFlowShim>(&CloneFlowL()));
       
   830 	if (ret != KErrNone)
       
   831 		{
       
   832 		Error(ret,MSessionControlNotify::EErrorCompleteConnect);
       
   833 		}
       
   834 	else
       
   835 	    {
       
   836         __ASSERT_DEBUG(shimFlow, User::Panic(KSpecAssert_ESockSSocksspshm, 35)); //otherwise we shouldn't be here
       
   837        	shimFlow->SetSSP(aSSP);
       
   838        	shimFlow->iFlowParams = iFlowParams;
       
   839 	    }
       
   840 	return shimFlow;
       
   841     }
       
   842 
       
   843 void CTransportFlowShim::ConnectComplete(CServProviderBase& aSSP)
       
   844 	{
       
   845 	CTransportFlowShim* shimFlow;
       
   846 	if ((shimFlow = CloneNSetSAP(aSSP)) != NULL)
       
   847 		{
       
   848 		__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 36));
       
   849 
       
   850 		// Store a pointer to the listening control session in case we need to unbind before
       
   851 		// the passively opened socket is accepted.
       
   852 		shimFlow->iListenerControlNotify = iSessionControlNotify;
       
   853 
       
   854 		iSessionControlNotify->ConnectComplete(*shimFlow);
       
   855 		}
       
   856 	}
       
   857 
       
   858 void CTransportFlowShim::ConnectComplete(CServProviderBase& aSSP,const TDesC8& aConnectData)
       
   859 	{
       
   860 //	CTransportFlowShim* shim = NULL;
       
   861 //	TRAPD(ret, shim = CTransportFlowShim::NewL(aSSP, NULL, iProtocolId));
       
   862 
       
   863 	CTransportFlowShim* shimFlow;
       
   864     if ((shimFlow = CloneNSetSAP(aSSP)) != NULL)
       
   865 		{
       
   866 		__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 37));
       
   867 		iSessionControlNotify->ConnectComplete(*shimFlow, aConnectData);
       
   868 		}
       
   869 	}
       
   870 
       
   871 void CTransportFlowShim::CanClose(MSocketNotify::TDelete aDelete)
       
   872 	{
       
   873 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() aDelete %d"), this, aDelete) );
       
   874 
       
   875 	if(iSessionControlNotify)
       
   876 		{
       
   877 		iDetaching = aDelete == MSocketNotify::EDetach;
       
   878 		iSessionControlNotify->CanClose(MSessionControlNotify::TDelete(aDelete));
       
   879         if(aDelete==MSocketNotify::EDetach)
       
   880             {
       
   881             iProvider = NULL;
       
   882             }
       
   883 		}
       
   884 	else
       
   885 		{
       
   886 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) );
       
   887 
       
   888 		// No control above us - likely cause is that we're the result of a passive open that
       
   889 		// hasn't yet been accepted.
       
   890 		Unbind();
       
   891 		}
       
   892 	}
       
   893 
       
   894 void CTransportFlowShim::CanClose(const TDesC8& aDisconnectData,MSocketNotify::TDelete aDelete)
       
   895 	{
       
   896 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() aDisconnectData %08x, aDelete %d"), this, aDisconnectData.Ptr(), aDelete) );
       
   897 
       
   898 	if(iSessionControlNotify)
       
   899 		{
       
   900         iDetaching = aDelete == MSocketNotify::EDetach;
       
   901 		iSessionControlNotify->CanClose(aDisconnectData, MSessionControlNotify::TDelete(aDelete));
       
   902 		if(aDelete==MSocketNotify::EDetach)
       
   903 			{
       
   904 			iProvider = NULL;
       
   905 			}
       
   906 		}
       
   907 	else
       
   908 		{
       
   909 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) );
       
   910 
       
   911 		// No control above us - likely cause is that we're the result of a passive open that
       
   912 		// hasn't yet been accepted.
       
   913 		Unbind();
       
   914 		}
       
   915 	}
       
   916 
       
   917 void CTransportFlowShim::Error(TInt anError, TUint anOperationMask)
       
   918 	{
       
   919 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tError() anError %d, anOperationMask %d"), this, anError, anOperationMask) );
       
   920 
       
   921 	NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=Error(%d)"),
       
   922 			this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), anError) )
       
   923 
       
   924 	if(iSessionControlNotify)
       
   925 		{
       
   926 		if (iSessionControlNotify->Error(anError, anOperationMask) != KErrNone)
       
   927 	    	{
       
   928 	    	if (iLowerFlow)
       
   929 	    		{
       
   930 	    		iLowerFlow->Unbind(NULL,NULL);
       
   931 	    		iLowerFlow = NULL;
       
   932 	    		}
       
   933 	        iLowerControl = NULL;
       
   934 	    	}
       
   935 		}
       
   936 	else
       
   937 		{
       
   938 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tError() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) );
       
   939 
       
   940 		// No control above us - likely cause is that we're the result of a passive open that
       
   941 		// hasn't yet been accepted.
       
   942 		iDetaching = MSocketNotify::EDetach;
       
   943 		Unbind();
       
   944 		}
       
   945 	}
       
   946 
       
   947 void CTransportFlowShim::Disconnect(void)
       
   948 	{
       
   949 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect()"), this) );
       
   950 
       
   951 	if(iSessionControlNotify)
       
   952 		{
       
   953 		iSessionControlNotify->Disconnect();
       
   954 		}
       
   955 	else
       
   956 		{
       
   957 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) );
       
   958 
       
   959 		// No control above us - likely cause is that we're the result of a passive open that
       
   960 		// hasn't yet been accepted.
       
   961 		iDetaching = MSocketNotify::EDetach;
       
   962 		Unbind();
       
   963 		}
       
   964 	}
       
   965 
       
   966 void CTransportFlowShim::Disconnect(TDesC8& aDisconnectData)
       
   967 	{
       
   968 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() aDisconnectData %08x"), this, aDisconnectData.Ptr()) );
       
   969 
       
   970 	if(iSessionControlNotify)
       
   971 		{
       
   972 		iSessionControlNotify->Disconnect(aDisconnectData);
       
   973 		}
       
   974 	else
       
   975 		{
       
   976 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) );
       
   977 
       
   978 		// No control above us - likely cause is that we're the result of a passive open that
       
   979 		// hasn't yet been accepted.
       
   980 		iDetaching = MSocketNotify::EDetach;
       
   981 		Unbind();
       
   982 		}
       
   983 	}
       
   984 
       
   985 void CTransportFlowShim::IoctlComplete(TDesC8 *aBuf)
       
   986 	{
       
   987 	__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 38));
       
   988 	iSessionControlNotify->IoctlComplete(aBuf);
       
   989 	}
       
   990 
       
   991 void CTransportFlowShim::NoBearer(const TDesC8& aConnectionParams)
       
   992 /**
       
   993 Upcall from protocol indicating no underlying bearer for the socket.
       
   994 @param aConnectionParams Additional connection parameters from the stack, in the form of a
       
   995 human readable string.  Initially, the required protocols (e.g. "protocol=ip").
       
   996 */
       
   997 	{
       
   998 	// *** NOTE ***
       
   999 	// overridden by CUpsTransportFlowShim::NoBearer() for UPS support
       
  1000 
       
  1001 	(void)aConnectionParams;
       
  1002 	LOG( ESockLog::ConnectionInfoPrintf(aConnectionParams, _L("CTransportFlowShim %08x:\tNoBearer()"), this) );
       
  1003 
       
  1004 	DoNoBearer(); // Do not care if actually posted, so no need to check return value
       
  1005 
       
  1006 	}
       
  1007 
       
  1008 void CTransportFlowShim::Bearer(const TDesC8& aConnectionInfo)
       
  1009 	{
       
  1010 	//we might need to translate the aConnectionInfo into "our" conn info format
       
  1011 	LOG( ESockLog::ConnectionInfoPrintf(aConnectionInfo, _L("CTransportFlowShim %08x:\tBearer()"), this) );
       
  1012 
       
  1013 #if defined(SYMBIAN_TRACE_ENABLE)
       
  1014 	const TSoIfConnectionInfo *info = REINTERPRET_CAST(const TSoIfConnectionInfo*, aConnectionInfo.Ptr());
       
  1015 	NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=Bearer(Iap %d, Network %d)"),
       
  1016 			this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), info->iIAPId, info->iNetworkId) )
       
  1017 #endif
       
  1018 
       
  1019 	if (TConnectionInfo::IsLocalBearer(aConnectionInfo))
       
  1020 		{
       
  1021 		return;
       
  1022 		}
       
  1023 
       
  1024 	iUseBearerErrors = ETrue;
       
  1025 	LocalName(iLocalAddress);
       
  1026 	iLocalAddressSet = ETrue;
       
  1027 	RemName(iRemoteAddress);
       
  1028 	iRemoteAddressSet = ETrue;
       
  1029 	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 41));	// legacy flows have no control side; should never get here
       
  1030 
       
  1031 	PostDataClientRouted();
       
  1032 	}
       
  1033 
       
  1034 TInt CTransportFlowShim::LockToConnectionInfo()
       
  1035 	{
       
  1036 	//bind provider with the selected connection
       
  1037 	// Note that the following SetOption() can result in an upcall into
       
  1038 	// CTransportFlowShim::Bearer() in the same stack frame.
       
  1039     TPckgBuf<TConnectionInfo> info;
       
  1040     if (Control(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), info) == KErrNone)
       
  1041 		{
       
  1042 		LOG(ESockLog::Printf(_L("CTransportFlowShim %08x:\tLockToConnectionInfo() Iap %d, Network %d"), this, info().iIapId, info().iNetId));
       
  1043 		NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=LockToConnectionInfo(Iap %d, Network %d)"),
       
  1044 				this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), info().iIapId, info().iNetId) )
       
  1045 
       
  1046 		TPckg<TSoIfConnectionInfo> ifInfo(iIfInfo);
       
  1047 	    ifInfo().iIAPId = info().iIapId;
       
  1048     	ifInfo().iNetworkId = info().iNetId;
       
  1049 		iProvider->SetOption(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), ifInfo);
       
  1050 		return KErrNone;
       
  1051 		}
       
  1052     else
       
  1053     	{
       
  1054     	LOG(ESockLog::Printf(_L("CTransportFlowShim %08x:\tLockToConnectionInfo()"), this));
       
  1055     	return KErrNotFound;
       
  1056     	}
       
  1057 	}
       
  1058 
       
  1059 void CTransportFlowShim::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
  1060     {
       
  1061     if (aMessage.IsMessage<TCFDataClient::TBindTo>() && !NoBearerGuard())
       
  1062     	{
       
  1063     	//TODO PROD RZ
       
  1064     	//This needs investigating and fixing. There are two cases for why is this needed here:
       
  1065     	//(1) Bearer mobility is the only scenario for unsolicited TBindTo
       
  1066     	//(hence checking the guard above). CTransportFlowShim cannot just migrate to the new, as the
       
  1067     	//socket above it needs to be rebound. mobility_761220:
       
  1068     	//  (1) opens and starts a connection
       
  1069     	//  (2) opens a socket against
       
  1070     	//  (3) sendreceive UDP data and expects (packet colouring) that data to go via IAP4.
       
  1071     	//  (4) migrates to another bearer (IAP5)
       
  1072     	//  (5) uses the same socket (without rebinding) to sendreceive data and expects
       
  1073     	//    the data to go via IAP4 again (despite migrating).
       
  1074     	//Talk to Ivan Kelly to find out if this is a requirement on the socket (stays connected
       
  1075     	//over the old until rebound) or is this a wrong test case.
       
  1076     	//If the former, ipscpr will need changing not to propagate TBindTo to its flows if they
       
  1077     	//don't ask.
       
  1078     	//(2) Rejoing this flow. During rejoin scenario, it's the new owner obtains its new
       
  1079     	//dataclient ('this') before ('this') dataclient knowing. The rejoin procedure is make
       
  1080     	//before break, hence it tries to apply the new owner, during which time the new
       
  1081     	//owner starts and hence attempts to TBindTo his new child. The child hates it
       
  1082     	//as it arrives from an unknown node. The rejoin protocol needs rethinking.
       
  1083 		RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(KErrNone).CRef());
       
  1084     	return;
       
  1085     	}
       
  1086     CNetworkFlow::ReceivedL(aSender, aRecipient, aMessage);
       
  1087 #ifdef SYMBIAN_NETWORKING_UPS
       
  1088 	// Allow derived classes to process received messages.
       
  1089 	//
       
  1090 	// Rationale for ProcessReceivedL() virtual:
       
  1091 	// The existing idiom whereby we call CNetworkFlow::ReceivedL() up front is awkward.
       
  1092 	// If we move that call into the derived class, the derived class can do its
       
  1093 	// specialised processing and then decide to call this base class method for any
       
  1094 	// remaining more general processing.  In this case, the ProcessReceivedL() would
       
  1095 	// not be required.  However, CTransportFlowShim will then become unusable if
       
  1096 	// instantiated on its own because the call to CNetworkFlow::ReceivedL() is not present.
       
  1097     TInt ret = ProcessReceivedL(aMessage);
       
  1098     if (ret == KErrNone || ret != KErrNotSupported)
       
  1099     	{
       
  1100     	return;	// PREQ1116 Productisation: RE-WORK ProcessReceivedL().  Perhaps return TBool indicating whether message processed.  Leave if a "real" error.  Extra arguments?
       
  1101     	}
       
  1102 #endif
       
  1103 
       
  1104    	if ( aMessage.IsMessage<TEBase::TError>() )
       
  1105    		{
       
  1106 		SubConnectionError(static_cast<TEBase::TError&>(aMessage));
       
  1107 		}
       
  1108    	else if (aMessage.IsMessage<TEBase::TCancel>())
       
  1109    		{
       
  1110    		// TCancel can be received as a result of a Connect() being cancelled on the socket and a
       
  1111    		// TBindToComplete() with an error being sent to the PRBindTo activity on our control provider.
       
  1112    		}
       
  1113    	else if (TEChild::ERealmId == aMessage.MessageId().Realm())
       
  1114 		{
       
  1115 		switch (aMessage.MessageId().MessageId())
       
  1116 			{
       
  1117 		case TEChild::TDestroy::EId :
       
  1118 			Destroy();
       
  1119 			break;
       
  1120 		default:
       
  1121 			//TODO - logging
       
  1122 			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
       
  1123 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 42)); //For debug configurations
       
  1124 			User::Leave(KErrNotSupported); //For release configurations
       
  1125 			}
       
  1126 		}
       
  1127 	else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
       
  1128 		{
       
  1129 		switch (aMessage.MessageId().MessageId())
       
  1130 			{
       
  1131 		case TCFDataClient::TStart::EId :
       
  1132 			StartFlowL(aSender);
       
  1133 			break;
       
  1134 		case TCFDataClient::TStop::EId :
       
  1135 			StopFlow(static_cast<TCFDataClient::TStop&>(aMessage));
       
  1136 			break;
       
  1137 		case TCFDataClient::TProvisionConfig::EId :
       
  1138 
       
  1139 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1140 			//Store the provision config message,
       
  1141 			//to store the Provision config message
       
  1142             StoreProvision(static_cast<TCFDataClient::TProvisionConfig&>(aMessage));
       
  1143 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1144 
       
  1145 			break;
       
  1146 		case TCFDataClient::TCommitBindTo::EId :
       
  1147 			/*TODO RZ PROD- mustn't just ignore TCommitBindTo - must implement*/
       
  1148 			break;
       
  1149 		case TCFDataClient::TBindTo::EId :
       
  1150 			{
       
  1151 			TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage));
       
  1152 			TRAPD(err,BindToL(bindToMsg));
       
  1153 			// Ensure that TBindToComplete message gets sent before TIdle so that it gets to the destination
       
  1154 			// before destroy processing.
       
  1155 			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(err).CRef());
       
  1156 			ProcessDCIdleState();	// in case we were waiting to send idle
       
  1157 			//If we have received TDataClientStart before (when we did not yet have a bearer),
       
  1158 			//we complete the start here as well
       
  1159 			if (err != KErrNone)
       
  1160 				{
       
  1161 				//If we have received TDataClientStart before (when we did not yet have a bearer),
       
  1162 				//we complete the start here as well
       
  1163 				if (iStartRequest.IsOpen())
       
  1164 					{
       
  1165 					CompleteStart(err);
       
  1166 					}
       
  1167                iBearerExpected = ETrue;
       
  1168 				}
       
  1169 			else
       
  1170 		    	{
       
  1171 				// If we get a TBindTo message then the TNoBearer request has succeeded
       
  1172 				// and we can inform the client.
       
  1173 		    	if (iSessionControlNotify)
       
  1174 		    		{
       
  1175 		    		iSessionControlNotify->SetLocalNameComplete();
       
  1176 		    		}
       
  1177 		        }
       
  1178 		    break;
       
  1179 			}
       
  1180 		default:
       
  1181 			//TODO - logging
       
  1182 			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
       
  1183 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 43)); //For debug configurations
       
  1184 			User::Leave(KErrNotSupported); //For release configurations
       
  1185 			}
       
  1186 		}
       
  1187 	else if (TCFFlow::ERealmId == aMessage.MessageId().Realm())
       
  1188 		{
       
  1189 		switch (aMessage.MessageId().MessageId())
       
  1190 			{
       
  1191 		case TCFFlow::TRejoin::EId :
       
  1192 			Rejoin(static_cast<TCFFlow::TRejoin&>(aMessage));
       
  1193 			break;
       
  1194 		default:
       
  1195 			//TODO - logging
       
  1196 			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
       
  1197 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 44)); //For debug configurations
       
  1198 			User::Leave(KErrNotSupported); //For release configurations
       
  1199 			}
       
  1200 		}
       
  1201 	else if (TCFInternalEsock::ERealmId == aMessage.MessageId().Realm())
       
  1202 		{
       
  1203 		switch (aMessage.MessageId().MessageId())
       
  1204 			{
       
  1205 	    case TCFInternalEsock::TFlowProvision::EId :
       
  1206 			iFlowParams = (static_cast<TCFInternalEsock::TFlowProvision&>(aMessage)).iFlowParams;
       
  1207 			break;
       
  1208 		default:
       
  1209 			//TODO - logging
       
  1210 			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
       
  1211 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 45)); //For debug configurations
       
  1212 			User::Leave(KErrNotSupported); //For release configurations
       
  1213 			}
       
  1214 		}
       
  1215 
       
  1216 //This is the case of Modulation change for a bearer.
       
  1217 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1218 	else if (TCFMessage::ERealmId == aMessage.MessageId().Realm())
       
  1219 		{
       
  1220 		switch (aMessage.MessageId().MessageId())
       
  1221 			{
       
  1222 		case TCFMessage::TTransportNotification::EId :
       
  1223           	//In case of modulation change,
       
  1224 			//extract the value from this message,
       
  1225 			//pass it to the shim to set the options for socket.
       
  1226 	   		SetProtocolOptions();
       
  1227 			break;
       
  1228         default:
       
  1229         	//TODO : Logging for error message
       
  1230         	__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 46)); //For debug configurations
       
  1231 			User::Leave(KErrNotSupported); //For release configurations
       
  1232 			}
       
  1233 		}
       
  1234 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1235 
       
  1236 	else if ( aMessage.IsMessage<TCFPeer::TJoinComplete>() )
       
  1237 		{;}
       
  1238 	else if ( aMessage.IsMessage<TCFControlProvider::TBearer>() )
       
  1239 		{
       
  1240 		//If we have received TDataClientStart before (when we did not yet have a bearer),
       
  1241 		//we complete the start here as well
       
  1242 		if (iStartRequest.IsOpen())
       
  1243 			{
       
  1244 			CompleteStart(KErrNone);
       
  1245 			}
       
  1246 		LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tReceivedL(): TBearer: iDeleteUponBearerReception %d"), this, iDeleteUponBearerReception) );
       
  1247 
       
  1248 		ClearNoBearerGuard();
       
  1249 		ProcessDCIdleState();
       
  1250 		NoBearerCompletion();		// may delete this !
       
  1251 		}
       
  1252 	else
       
  1253 		{
       
  1254 		//TODO - logging
       
  1255 		//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
       
  1256     	__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 47)); //For debug configurations
       
  1257     	User::Leave(KErrNotSupported); //For release configurations
       
  1258 		}
       
  1259     }
       
  1260 
       
  1261 void CTransportFlowShim::NoBearerCompletion()
       
  1262 	{
       
  1263 	iBearerExpected = EFalse;
       
  1264 	if (iDeleteUponBearerReception)
       
  1265 		{
       
  1266 		delete this;
       
  1267 		}
       
  1268 	}
       
  1269 
       
  1270 const TNodeId& CTransportFlowShim::NodeId() const
       
  1271 	{
       
  1272 	return Id();
       
  1273 	}
       
  1274 
       
  1275 void CTransportFlowShim::CompleteStart(TInt aError)
       
  1276 	{
       
  1277 	if (aError==KErrNone)
       
  1278 		{
       
  1279 		iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
       
  1280 		iIsStarted = ETrue;
       
  1281 		iIsStopped = EFalse;
       
  1282 		}
       
  1283 	else
       
  1284 		{
       
  1285 		iStartRequest.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(),aError).CRef());
       
  1286 		}
       
  1287 	iStartRequest.Close();
       
  1288 	}
       
  1289 
       
  1290 void CTransportFlowShim::SubConnectionError(const TEBase::TError& errorMsg, TUint anOperationMask)
       
  1291 	{
       
  1292 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() errorMsg.iValue %d, anOperationMask %d"), this, errorMsg.iValue, anOperationMask) );
       
  1293 
       
  1294 	if (errorMsg.iMsgId == TCFControlProvider::TNoBearer::Id())
       
  1295 		{
       
  1296 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - clearing no-bearer guard"), this) );
       
  1297 		ClearNoBearerGuard();
       
  1298 #ifdef SYMBIAN_NETWORKING_UPS
       
  1299 		ProcessDCIdleState();
       
  1300 #endif
       
  1301 		NoBearerCompletion();
       
  1302 		}
       
  1303 
       
  1304 	if (IsBoundToSession())
       
  1305 	    {
       
  1306 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - calling Error() function"), this) );
       
  1307     	Error(errorMsg.iValue, anOperationMask);
       
  1308 	    }
       
  1309 	else if (iHostResolverNotify)
       
  1310 	    {
       
  1311 		LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - passing to host resolver's Error() function"), this) );
       
  1312 	    iHostResolverNotify->Error(errorMsg.iValue);
       
  1313 	    }
       
  1314 	}
       
  1315 
       
  1316 void CTransportFlowShim::BindToL(TCFDataClient::TBindTo& aBindTo)
       
  1317 /**
       
  1318 Request from control side (at network layer) to indicate that the SubConnection is
       
  1319 up and running and that we should bind to a Flow below.
       
  1320 
       
  1321 @param aLowerFlow Flow below to bind to.
       
  1322 */
       
  1323 	{
       
  1324 	//provisioning message must come before bindto in case we didn't get it after we've joined
       
  1325 	//the sub-connection
       
  1326 
       
  1327 	NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"),
       
  1328 			this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) )
       
  1329 
       
  1330 	if (iShuttingDown)
       
  1331 		{
       
  1332 		User::Leave(KErrCancel);
       
  1333 		return;
       
  1334 		}
       
  1335 
       
  1336 	CNetworkFlow::BindToL(aBindTo);
       
  1337 	if (iLowerFlow && IsBoundToSession())
       
  1338 		{
       
  1339 		LockToConnectionInfo();
       
  1340 		LocalName(iLocalAddress);
       
  1341 		iLocalAddressSet = ETrue;
       
  1342 		RemName(iRemoteAddress);
       
  1343 		iRemoteAddressSet = ETrue;
       
  1344 		__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 48));	// legacy flows have no control side; should never get here
       
  1345 		}
       
  1346 	else if (iHostResolverNotify)
       
  1347 	    {//workaroud to indicate to CHostResolver we've got connection info
       
  1348 	    if (aBindTo.iNodeId.Ptr())
       
  1349 	        {
       
  1350     	    iHostResolverNotify->StartSending();
       
  1351 	        }
       
  1352 	    else
       
  1353 	        {
       
  1354             iHostResolverNotify->Error(KErrDisconnected);
       
  1355 	        }
       
  1356 	    }
       
  1357 
       
  1358 
       
  1359 
       
  1360 	}
       
  1361 
       
  1362 
       
  1363 void CTransportFlowShim::Rejoin(const TCFFlow::TRejoin& aRejoinMessage)
       
  1364     {
       
  1365 	LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tRejoin()"), this ));
       
  1366 	iSubConnectionProvider.Close();
       
  1367 	iSubConnectionProvider.Open(TNodeCtxId(0, aRejoinMessage.iNodeId));
       
  1368     //If already bound there's a potential need to rebind.
       
  1369     //As the new control provider for the flow - if different than
       
  1370     //the current, rebind.
       
  1371     if (iLowerFlow)
       
  1372         {
       
  1373         PostNoBearer();
       
  1374         }
       
  1375     }
       
  1376 
       
  1377 void CTransportFlowShim::StartFlowL(const TRuntimeCtxId& aSender)
       
  1378 	{
       
  1379 	__ASSERT_DEBUG(!iIsStarted, User::Panic(KSpecAssert_ESockSSocksspshm, 49));
       
  1380 	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 50));	// legacy flows have no control side; should never get here
       
  1381 
       
  1382 	//We will wait for it and complete the start after we have received it
       
  1383 	User::LeaveIfError(iStartRequest.Open(iSubConnectionProvider, aSender));
       
  1384 
       
  1385 	if (iDCIdle != EClientsPresent)
       
  1386 		{
       
  1387 		iStartRequest.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(), KErrNotReady).CRef());
       
  1388 		iStartRequest.Close();
       
  1389 		return;
       
  1390 		}
       
  1391 
       
  1392 	if (iLowerFlow)
       
  1393 		{
       
  1394 		iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
       
  1395 		iStartRequest.Close();
       
  1396 		iIsStarted = ETrue;
       
  1397 		iIsStopped = EFalse;
       
  1398 		return;
       
  1399 		}
       
  1400 
       
  1401 	//We need a bearer
       
  1402 		PostNoBearer(); //Ask for bearer if not requested already
       
  1403 
       
  1404 	}
       
  1405 
       
  1406 void CTransportFlowShim::StopFlow(TCFDataClient::TStop& aMessage)
       
  1407 	{
       
  1408 	__ASSERT_DEBUG(iIsStarted, User::Panic(KSpecAssert_ESockSSocksspshm, 51)); //Must be started now
       
  1409 	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 52));	// legacy flows have no control side; should never get here
       
  1410 
       
  1411 	// We need to error the socket if the lower protocol stack is not going to do this.  Once a
       
  1412 	// Bearer() upcall has been received, the lower protocol will call Error() if the connection
       
  1413 	// goes down.  Before this point, the lower protocol will not call Error(), so StopFlow() calls
       
  1414 	// from the SCPR are used to error the socket (if the interface start fails).
       
  1415 	//
       
  1416 	// The main scenario is the TCP/IP stack as lower protocol which will only call Error() once it
       
  1417 	// has attached a flow to a route (and hence an interface) which, in turn, only occurs once the
       
  1418 	// interface is up and data has been sent over the socket.  Note that opening an RSocket on an
       
  1419 	// RConnection but not transferring any data will not cause the TCP/IP stack to attach the flow
       
  1420 	// to the route and hence not call Error() if the interface comes down.
       
  1421 
       
  1422 	if (IsBoundToSession() && !iUseBearerErrors)
       
  1423 	    {
       
  1424     	Error(aMessage.iValue, EErrorAllOperations);
       
  1425 	    }
       
  1426 
       
  1427 	if (iLowerFlow)
       
  1428 		{
       
  1429 		iLowerFlow->Unbind(NULL,NULL);
       
  1430 		iLowerFlow = NULL;
       
  1431 		}
       
  1432 	iLowerControl = NULL;
       
  1433 
       
  1434 	iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(aMessage.iValue).CRef());
       
  1435 	iIsStarted = EFalse;
       
  1436 	iIsStopped = ETrue;
       
  1437 	}
       
  1438 
       
  1439 void CTransportFlowShim::InitDestroy()
       
  1440 	{
       
  1441     __ASSERT_DEBUG(iDCIdle <= EClientsPresent, User::Panic(KSpecAssert_ESockSSocksspshm, 53));
       
  1442     iDCIdle = EIdle;
       
  1443 
       
  1444     if(iSubConnectionProvider.IsOpen())	// legacy flows have no control side
       
  1445     	{
       
  1446     	ProcessDCIdleState();
       
  1447     	}
       
  1448 	else
       
  1449 		{
       
  1450 		DeleteThisFlow();
       
  1451 		}
       
  1452 	}
       
  1453 
       
  1454 void CTransportFlowShim::Destroy()
       
  1455 	{
       
  1456 	DeleteThisFlow();
       
  1457 	}
       
  1458 
       
  1459 void CTransportFlowShim::PostNoBearer()
       
  1460 	{
       
  1461 	if (!NoBearerGuard())
       
  1462 		{
       
  1463 		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TNoBearer().CRef());
       
  1464 		SetNoBearerGuard();
       
  1465 		}
       
  1466 	}
       
  1467 
       
  1468 void CTransportFlowShim::PostDataClientRouted()
       
  1469 	{
       
  1470  	if (iLocalAddressSet && iRemoteAddressSet
       
  1471 	&& iRemoteAddress.Family() != KAFUnspec && !iDataClientRoutedGuard)
       
  1472 		{
       
  1473 		iSubConnectionProvider.PostMessage(
       
  1474 			Id(),
       
  1475 			TCFIPMessages::TDataClientRouted(
       
  1476 				TAddrUpdate(
       
  1477 					iLocalAddress,
       
  1478 					iRemoteAddress,
       
  1479 					iFlowParams.iProtocol,
       
  1480 					iIfInfo.iIAPId)
       
  1481 				).CRef()
       
  1482 			);
       
  1483 		iDataClientRoutedGuard = ETrue;
       
  1484 		}
       
  1485 	}
       
  1486 
       
  1487 void CTransportFlowShim::ClearDataClientRoutedGuard()
       
  1488 	{
       
  1489 	iDataClientRoutedGuard = EFalse;
       
  1490 	}
       
  1491 
       
  1492 
       
  1493 /*
       
  1494 Store the provision information passed from the Control side.
       
  1495 @param TProvisionConfig Message recd.
       
  1496 */
       
  1497 void CTransportFlowShim::StoreProvision(TCFDataClient::TProvisionConfig& aMessage)
       
  1498 	{
       
  1499 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1500 	//find access point inforamtion from the message
       
  1501 	iAccessPointConfig.Close();
       
  1502 	iAccessPointConfig.Open(aMessage.iConfig);
       
  1503 	//Find extension appended at NetMcpr and store it
       
  1504 	//Presently will extract CSAPSetOpt window extensions
       
  1505 	ExtractSetOptExtensions();
       
  1506 #else
       
  1507 	(void)aMessage;
       
  1508 #endif
       
  1509 	}
       
  1510 /*
       
  1511 Extract extensions appended to TProvisionConfig specific to IPTransport.
       
  1512 */
       
  1513 void CTransportFlowShim::ExtractSetOptExtensions()
       
  1514 	{
       
  1515 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1516 	//Extract TCP receive window specific provisionconfig extension.
       
  1517 	iProtocolOptions = static_cast< const CSAPSetOpt*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CSAPSetOpt::EUid,CSAPSetOpt::ETypeId)));
       
  1518 #endif
       
  1519 	}
       
  1520 
       
  1521 #ifdef SYMBIAN_NETWORKING_UPS
       
  1522 
       
  1523 TBool CTransportFlowShim::ActivityRunning()
       
  1524 /**
       
  1525 Determine whether we are in the middle of a NoBearer activity.
       
  1526 
       
  1527 In other words, we are waiting for a response from a previously transmitted TNoBearer.
       
  1528 
       
  1529 @return ETrue if in the middle of one of this activity, else EFalse.
       
  1530 */
       
  1531 	{
       
  1532 	return NoBearerGuard();
       
  1533 	}
       
  1534 
       
  1535 //
       
  1536 // Default implementations of CTransportFlowShim virtuals.
       
  1537 //
       
  1538 
       
  1539 TInt CTransportFlowShim::SetupForNoBearerOnSend()
       
  1540 	{
       
  1541 	return KErrNotSupported;
       
  1542 	}
       
  1543 
       
  1544 void CTransportFlowShim::PreUnbind()
       
  1545 	{
       
  1546 	}
       
  1547 
       
  1548 TInt CTransportFlowShim::ProcessReceivedL(TSignatureBase& /*aCFMessage*/)
       
  1549 	{
       
  1550 	return KErrNotSupported;
       
  1551 	}
       
  1552 
       
  1553 //
       
  1554 // CUpsTransportFlowShim methods
       
  1555 //
       
  1556 // This class contains User Prompt Service (UPS) specific functionality.
       
  1557 //
       
  1558 
       
  1559 CUpsTransportFlowShim* CUpsTransportFlowShim::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf)
       
  1560 /**
       
  1561 Create a new CUpsTransportFlowShim instanace.
       
  1562 
       
  1563 Note: this method replaces CTransportFlowShim::NewL() in UPS builds.
       
  1564 */
       
  1565 	{
       
  1566 	return new (ELeave) CUpsTransportFlowShim(aFactory, aSubConn, aProtocolIntf);
       
  1567 	}
       
  1568 
       
  1569 TInt CUpsTransportFlowShim::SetupForNoBearerOnSend()
       
  1570 /**
       
  1571 Called just before a TNoBearer message is posted for Host Resolver processing.
       
  1572 
       
  1573 Perform the Platform Security capability check and populate the UPS Access Point Config (APC) extension.
       
  1574 
       
  1575 @return KErrNone or a system wide error code.
       
  1576 */
       
  1577 	{
       
  1578 	// For UPS, the capability check has been moved from the provider SAP to here so that
       
  1579 	// the capability check result is available at the time of the NoBearer message being sent.
       
  1580 	__ASSERT_DEBUG(iSecurityChecker, User::Panic(KSpecAssert_ESockSSocksspshm, 54));
       
  1581 	TInt result = iSecurityChecker->CheckPolicy(KPolicyNetworkServices, "UpsTransportFlowShim (SetupForNoBearerOnSend)");
       
  1582 
       
  1583 	// At this point, result can contain:
       
  1584 	//
       
  1585 	// KErrNone					Capability check passed.
       
  1586 	// KErrPermissionDenied		Capability check failed.
       
  1587 	// KErrCompletion			Special error code that instructs us not to perform any UPS check.
       
  1588 	//							This is a means for upper layers to disable UPS checking in circumstances
       
  1589 	//							where the UPS check will be catered for by a higher layer.
       
  1590 	if (result != KErrCompletion)
       
  1591 		{
       
  1592 		if (UpsEnabled())
       
  1593 			{
       
  1594 			// UPS enabled - fill in the APC structure associated with TNoBearer message
       
  1595 			PopulateUpsExtension(result);
       
  1596 			}
       
  1597 		else
       
  1598 			{
       
  1599 			// UPS disabled - fall back to the Platform Security check
       
  1600 			if (result != KErrNone)
       
  1601 				{
       
  1602 				return TSendResult(result);
       
  1603 				}
       
  1604 			}
       
  1605 		}
       
  1606 	return KErrNone;
       
  1607 	}
       
  1608 
       
  1609 void CUpsTransportFlowShim::PreUnbind()
       
  1610 /**
       
  1611 Called just before an unbind happens.
       
  1612 
       
  1613 Ensure that we cancel any running activities.
       
  1614 
       
  1615 (there are no activities on the data side in the formal sense - the term is used
       
  1616 to describe NoBearer processing happening locally).
       
  1617 */
       
  1618 	{
       
  1619 	if (ActivityRunning())
       
  1620 		{
       
  1621 		// @TODO PREQ1116 - should we be able to have a NoBearer and a PolicyCheckRequest pending
       
  1622 		// at the same time ?  Should we prevent it?
       
  1623 
       
  1624 		// Cancel any pending NoBearer activity.  This has become necessary because the UPS authorisation
       
  1625 		// can cause the NoBearer activity to be pending for an indefinate period of time.  When the
       
  1626 		// cancel reaches the MCpr, the UPS authorisation will be cancelled and a TError will eventually
       
  1627 		// be received and processed in SubConnectionError().
       
  1628 		iSubConnectionProvider.PostMessage(Id(), Messages::TEBase::TCancel().CRef());
       
  1629 		}
       
  1630 	}
       
  1631 
       
  1632 TInt CUpsTransportFlowShim::SetOption(TUint aLevel, TUint aName, const TDesC8 &anOption)
       
  1633 /**
       
  1634 Process SetOption() requests from upper layer
       
  1635 */
       
  1636 	{
       
  1637 	if (aLevel == KSOLProvider)
       
  1638 		{
       
  1639 		if (aName == KSoOwnerInfo)
       
  1640 			{
       
  1641 			// Upper layer communicating process and thread id of client opening subsession.
       
  1642 			__ASSERT_DEBUG(anOption.Size() == sizeof(TSoOwnerInfo), User::Panic(KSpecAssert_ESockSSocksspshm, 55));
       
  1643 
       
  1644 			const TSoOwnerInfo* soOwnerInfoPtr = reinterpret_cast <const TSoOwnerInfo*> (anOption.Ptr());
       
  1645 			__ASSERT_DEBUG(soOwnerInfoPtr, User::Panic(KSpecAssert_ESockSSocksspshm, 56));
       
  1646 
       
  1647 			iThreadId  = soOwnerInfoPtr->iThreadId;
       
  1648 			iProcessId = soOwnerInfoPtr->iProcessId;
       
  1649 			}
       
  1650 		else
       
  1651 		if (aName == KSoSetPlatSecApi)
       
  1652 			{
       
  1653 			// Upper layer communicating an 'M' class instance that can be used for retrieving
       
  1654 			// process and thread id of client performing current operation.
       
  1655 			__ASSERT_DEBUG(anOption.Size() == sizeof(const MPlatsecApiExt*), User::Panic(KSpecAssert_ESockSSocksspshm, 57));
       
  1656 			iPlatsecIf = *reinterpret_cast <const MPlatsecApiExt* const *> (anOption.Ptr());
       
  1657 			}
       
  1658 
       
  1659 		if (IsHostResolver())
       
  1660 			{
       
  1661 			// For Host Resolvers, the SetOption() is only for us to store the thread and process id,
       
  1662 			// so we are complete.  There is no iProvider in this case to propagate the call to.
       
  1663 			__ASSERT_DEBUG(Provider() == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 58));
       
  1664 			return KErrNone;
       
  1665 			}
       
  1666 		}
       
  1667 
       
  1668 	return CTransportFlowShim::SetOption(aLevel, aName, anOption);
       
  1669 	}
       
  1670 
       
  1671 TInt CUpsTransportFlowShim::SecurityCheck(MProvdSecurityChecker* aChecker)
       
  1672 /**
       
  1673 Called from upper layer to ask the SAP provider to perform a security policy check
       
  1674 on the client process.
       
  1675 
       
  1676 @param aChecker Security checker class instance
       
  1677 @return KErrNone or a system wide error code
       
  1678 */
       
  1679 	{
       
  1680 	// Save away the security checker class so that we can perform capability checking
       
  1681 	// here instead of in the TCP/IP stack.
       
  1682 	//
       
  1683 	// Note: iSecurityChecker can get overwritten as a result of ProtocolManager::TransferSocketL(),
       
  1684 	// so don't ASSERT(iSecurityChecker == NULL).
       
  1685 	iSecurityChecker = aChecker;
       
  1686 
       
  1687 	if (Provider())
       
  1688 		{
       
  1689 		// Sockets
       
  1690 		__ASSERT_DEBUG(!IsHostResolver(), User::Panic(KSpecAssert_ESockSSocksspshm, 59));
       
  1691 		return Provider()->SecurityCheck(aChecker);
       
  1692 		}
       
  1693 	else
       
  1694 		{
       
  1695 		// Host Resolvers
       
  1696 		__ASSERT_DEBUG(IsHostResolver(), User::Panic(KSpecAssert_ESockSSocksspshm, 60));
       
  1697 		return KErrNone;
       
  1698 		}
       
  1699 	}
       
  1700 
       
  1701 void CUpsTransportFlowShim::GetProcessAndThreadId(TProcessId& aProcessId, TThreadId& aThreadId) const
       
  1702 /**
       
  1703 Retrieve the process and thread id corresponding to the current Socket/Host Resolver request.
       
  1704 
       
  1705 The iProcessId and iThreadId variables contain the ids at the time of subsession open, which
       
  1706 is not necessarily the same as the ids of the client performing the actual request.  The
       
  1707 call to iPlatsecIf->GetProcessAndThreadId() will actually go to the layer above for processing
       
  1708 and retrieve the ids associated with the current pending request.
       
  1709 
       
  1710 @param aProcessId variable receiving process id (out)
       
  1711 @param aThreadId variable receiveing thread id (out)
       
  1712 @return KErrNone, else a system wide error code.
       
  1713 */
       
  1714 	{
       
  1715 	TInt err = KErrGeneral;
       
  1716 	if (iPlatsecIf)
       
  1717 		{
       
  1718 		err = iPlatsecIf->GetProcessAndThreadId(aProcessId, aThreadId);
       
  1719 		}
       
  1720 
       
  1721 	if (err != KErrNone)
       
  1722 		{
       
  1723 		aProcessId = iProcessId;
       
  1724 		aThreadId = iThreadId;
       
  1725 		}
       
  1726 	}
       
  1727 
       
  1728 void CUpsTransportFlowShim::NoBearer(const TDesC8& aConnectionParams)
       
  1729 /**
       
  1730 Upcall from protocol indicating no underlying bearer for the socket.
       
  1731 @param aConnectionParams Additional connection parameters from the stack, in the form of a
       
  1732 human readable string.  Initially, the required protocols (e.g. "protocol=ip").
       
  1733 
       
  1734 This method overrides CTransportFlowShim::NoBearer() for UPS specific handling.
       
  1735 */
       
  1736 	{
       
  1737 	(void)aConnectionParams;
       
  1738 	LOG( ESockLog::Printf(_L8("CUpsTransportFlowShim %08x:\tNoBearer(%S)"), this, &aConnectionParams) );
       
  1739 
       
  1740 	// Perform the Platform Security check (moved from the Provider SAP to here in order to
       
  1741 	// obtain the platsec result as part of UPS processing).
       
  1742 
       
  1743 	TInt result = iSecurityChecker->CheckPolicy(KPolicyNetworkServices, "TransportFlowShim (NoBearer)");
       
  1744 
       
  1745 	NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=NoBearer(%S)"),
       
  1746 			this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), &aConnectionParams) )
       
  1747 
       
  1748 	// At this point, result can contain:
       
  1749 	//
       
  1750 	// KErrNone					Capability check passed.
       
  1751 	// KErrPermissionDenied		Capability check failed.
       
  1752 	// KErrCompletion			Special error code that instructs us not to perform any UPS check.
       
  1753 	//							This is a means for upper layers to disable UPS checking in circumstances
       
  1754 	//							where the UPS check will be catered for by a higher layer.
       
  1755 
       
  1756 	TBool disableUpsCheck = (result == KErrCompletion);
       
  1757 	if (!disableUpsCheck && !UpsEnabled())
       
  1758 		{
       
  1759 		// UPS disabled - fall back to the Platform Security check
       
  1760 		if (result != KErrNone)
       
  1761 			{
       
  1762 			Error(result, MSocketNotify::EErrorSend | MSocketNotify::EErrorConnect);
       
  1763 			return;
       
  1764 			}
       
  1765 		}
       
  1766 
       
  1767 	if(!IsStopped())
       
  1768 		{ // Prevent sending NoBearer if DataClientStop was received
       
  1769 		ParseNoBearerParams(aConnectionParams);
       
  1770 		if (iIsScoped)
       
  1771 		    {
       
  1772 		    if (!disableUpsCheck && UpsEnabled())
       
  1773 		        {
       
  1774 	            // Do not perform standard NoBearer() processing for "gratuitous" NoBearer() calls.  The
       
  1775 	            // TCP/IP stack already has enough scope information to select an interface, but this
       
  1776 	            // probably will be different from the "default" implicit interface that the control side will
       
  1777 	            // select.  The consequence is that the TransportFlowShim could end up being associated with the
       
  1778 	            // wrong SCpr.  Note that this is not a problem introduced by UPS functionality - it exists in
       
  1779 	            // the Networking Subsystem anyway.  The "Bearer()-only" cases in pre-UPS code do not result in
       
  1780 	            // the TCP/IP stack generating a NoBearer() (just a Bearer()), so the TransportFlowShim never
       
  1781 	            // gets associated with any SCpr.  We are just replicating this behaviour for UPS functionality,
       
  1782 	            // by performing a TPolicyCheckRequest sequence for the sake of UPS checking, but otherwise the
       
  1783 	            // behaviour mirrors what is already present (i.e. does nothing else).
       
  1784 	            PostPolicyCheckRequest(result);
       
  1785 		        }
       
  1786             else
       
  1787                 {
       
  1788                 // If no UPS handling is required, tell the TCP/IP stack that it can go ahead and route the flow.
       
  1789 				IssueScopedNoBearerResponse();
       
  1790                 }
       
  1791 		    }
       
  1792 		else
       
  1793 		if (LockToConnectionInfo() != KErrNone)
       
  1794 		    {
       
  1795 			__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 61));	// legacy flows have no control side; should never get here
       
  1796 			// If UPS is enabled, fill in the APC structure to accompany the TNoBearer
       
  1797 			// Do this even if disableUpsCheck is set so that the APC will contain KErrCompletion.
       
  1798 			if (UpsEnabled())
       
  1799 				{
       
  1800 				PopulateUpsExtension(result);
       
  1801 				}
       
  1802 	        PostNoBearer();
       
  1803 		    }
       
  1804 		ClearUseBearerErrors();
       
  1805 		ClearDataClientRoutedGuard();
       
  1806 		}
       
  1807 	else
       
  1808 	    {
       
  1809 	    // Return an error on an attempt to issue a SendTo() on an explicit socket (datagram) whose corresponding
       
  1810 	    // connection has gone down (BR2639).  Note that the use of KErrDisconnected should NOT be documented -
       
  1811 	    // in future, we may wish to return the same error as the connection itself experienced.
       
  1812 	    Error(KErrDisconnected, MSessionControlNotify::EErrorSend);
       
  1813 	    }
       
  1814 	}
       
  1815 
       
  1816 void CUpsTransportFlowShim::PopulateUpsExtension(TInt aPolicyCheckResult) const
       
  1817 /**
       
  1818 Populate the UPS Access Point Config structure with the required information in preparation for
       
  1819 a TNoBearer message to be transmitted.
       
  1820 
       
  1821 @param aPolicyCheckResult result of Platform Security check
       
  1822 */
       
  1823 	{
       
  1824 	__ASSERT_DEBUG(iUpsExtension, User::Panic(KSpecAssert_ESockSSocksspshm, 62));
       
  1825 	iUpsExtension->SetPolicyCheckResult(aPolicyCheckResult);
       
  1826 
       
  1827 	TProcessId processId;
       
  1828 	TThreadId threadId;
       
  1829 	GetProcessAndThreadId(processId, threadId);
       
  1830 
       
  1831 	iUpsExtension->SetProcessId(processId);
       
  1832 	iUpsExtension->SetThreadId(threadId);
       
  1833 
       
  1834 	if (IsHostResolver())
       
  1835 		{
       
  1836 		// Null destination name for Host Resolvers.
       
  1837 		iUpsExtension->ResetDestinationAddr();
       
  1838 		iUpsExtension->SetDestinationAddrType(ETNone);
       
  1839 		}
       
  1840 	else
       
  1841 		{
       
  1842 		// @TODO PREQ1116 - something better than this cast?  For example, argument to
       
  1843 		// SetDestinationAddr() could become a "const TDesC8&" perhaps (without worrying about
       
  1844 		// error checking) ?
       
  1845 		iUpsExtension->SetDestinationAddr(static_cast<TUpsDestinationAddr>(iRemoteAddress));
       
  1846 		iUpsExtension->SetDestinationAddrType(ETSockAddress);
       
  1847 		}
       
  1848 	}
       
  1849 
       
  1850 
       
  1851 void CUpsTransportFlowShim::PostPolicyCheckRequest(TInt aPolicyCheckResult)
       
  1852 /**
       
  1853 Post a TPolicyCheckRequest message to the SCpr
       
  1854 
       
  1855 @param aPolicyCheckResult result of Platform Security check
       
  1856 */
       
  1857 	{
       
  1858 	if (!PolicyCheckRequestPending())
       
  1859 		{
       
  1860 		__ASSERT_DEBUG(UpsEnabled(), User::Panic(KSpecAssert_ESockSSocksspshm, 63));	// UPS should not be "short circuited" off
       
  1861 
       
  1862 		TProcessId processId;
       
  1863 		TThreadId threadId;
       
  1864 		GetProcessAndThreadId(processId, threadId);
       
  1865 
       
  1866 		const TPolicyCheckRequestParams params(processId, threadId, aPolicyCheckResult, static_cast<TUpsDestinationAddr>(iRemoteAddress), ETSockAddress);
       
  1867 		iSubConnectionProvider.PostMessage(Id(), UpsMessage::TPolicyCheckRequest(params).CRef());
       
  1868 		SetPolicyCheckRequestPending(ETrue);
       
  1869 		}
       
  1870 	}
       
  1871 
       
  1872 void CUpsTransportFlowShim::ProcessPolicyCheckResponse(const UpsMessage::TPolicyCheckResponse& aResponse)
       
  1873 /**
       
  1874 Process a TPolicyCheckResponse from the SCpr.
       
  1875 
       
  1876 If UPS authorisation was granted, prod the TCP/IP stack into re-attaching the flow (based on the original
       
  1877 scope id in the socket address).
       
  1878 
       
  1879 @param aResponse TPolicyCheckResponse message
       
  1880 */
       
  1881 	{
       
  1882 	SetPolicyCheckRequestPending(EFalse);
       
  1883 
       
  1884 	if (iDCIdle == EIdle)
       
  1885 		{
       
  1886 		ProcessDCIdleState();
       
  1887 		}
       
  1888 	else
       
  1889 		{
       
  1890 		if (aResponse.iValue == KErrNone)
       
  1891 			{
       
  1892 			if (iIsScoped)
       
  1893 				{
       
  1894 				// If socket address already has a scope id, do not tell the stack to use our
       
  1895 				// idea of NetworkId.  If we do, our idea of the NetworkId could be a mismatch
       
  1896 				// with the existing scope id, and we could end up with an SCPR which represents a
       
  1897 				// different interface from the one that the TCP/IP stack has chosen based on the scope
       
  1898 				// id.  Use the special KNetworkIdFromAddress value for NetworkId which the TCP/IP stack
       
  1899 				// recognises as meaning "attempt to attach the flow to a route, but determine the
       
  1900 				// NetworkId from the socket address, as you've already indicated in the NoBearer()
       
  1901 				// that you have enough information to do so".
       
  1902 				//
       
  1903 				// This code has become necessary due to the UPS support, which forces the
       
  1904 				// TCP/IP stack to issue NoBearer() calls in circumstances where it never used to
       
  1905 				// before, to give an opportunity to perform UPS authorisation.
       
  1906 				IssueScopedNoBearerResponse();
       
  1907 				}
       
  1908 			}
       
  1909 		else
       
  1910 			{
       
  1911 			Error(aResponse.iValue, MSocketNotify::EErrorSend | MSocketNotify::EErrorConnect);
       
  1912 			}
       
  1913 		}
       
  1914 	}
       
  1915 
       
  1916 void CUpsTransportFlowShim::IssueScopedNoBearerResponse()
       
  1917 /**
       
  1918 After a gratuitous NoBearer() upcall has been issued to us (to allow a chance for UPS checking to occur before
       
  1919 a flow is routed), issue the response to the TCP/IP stack indicating that it can now route the flow and continue.
       
  1920  */
       
  1921     {
       
  1922     TSoIfConnectionInfo info;
       
  1923     TPckg<TSoIfConnectionInfo> ifInfo(info);
       
  1924     info.iIAPId = 0;
       
  1925     info.iNetworkId = KNetworkIdFromAddress;
       
  1926     __ASSERT_DEBUG(Provider(), User::Panic(KSpecAssert_ESockSSocksspshm, 64));
       
  1927     SetIfInfo(info);
       
  1928     Provider()->SetOption(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), ifInfo);
       
  1929     }
       
  1930 
       
  1931 void CUpsTransportFlowShim::ParseNoBearerParams(const TDesC8& aConnectionParams)
       
  1932 /**
       
  1933 Parse the descriptor passed in NoBearer() upcall.
       
  1934 
       
  1935 Main raison d'etre for this routine is to check whether the "scoped" string was
       
  1936 part of the descriptor contents (indicating a "gratuitous" NoBearer()).
       
  1937 
       
  1938 @param aConnectionParams Argument passed in NoBearer() upcall from lower layer.
       
  1939 */
       
  1940 	{
       
  1941 	_LIT8(KScoped, "scoped");
       
  1942 	if (aConnectionParams.Find(KScoped()) != KErrNotFound)
       
  1943 		{
       
  1944 		// "scoped" string signifies a "gratuitous" NoBearer().  The flow could have been routed
       
  1945 		// without a NoBearer() (i.e. it was scoped enough to route it), but the NoBearer() was
       
  1946 		// generated anyway so that ESock could perform UPS checking before routing it.
       
  1947 		iIsScoped = ETrue;
       
  1948 		}
       
  1949 	else
       
  1950 		{
       
  1951 		iIsScoped = EFalse;
       
  1952 		}
       
  1953 	}
       
  1954 
       
  1955 TInt CUpsTransportFlowShim::ProcessReceivedL(TSignatureBase& aCFMessage)
       
  1956 /*
       
  1957 Process any SCpr messages specific to UPS functionality.
       
  1958 
       
  1959 Called from base class (CTransportFlowShim) before it attempts to process the incoming message.
       
  1960 
       
  1961 @param aCFMessage Message from SCpr
       
  1962 @return KErrNone if we have handled the incoming message and no more processing is necessary,
       
  1963 KErrNotSupported if have not handled the incoming message, else a system wide error code.
       
  1964 */
       
  1965     {
       
  1966 	// Check for special UPS messages.
       
  1967 	if (UpsMessage::ERealmId == aCFMessage.MessageId().Realm())
       
  1968 		{
       
  1969         switch (aCFMessage.MessageId().MessageId())
       
  1970 		  {
       
  1971 		case UpsMessage::TPolicyCheckResponse::EId :
       
  1972 			{
       
  1973 			// Support for UPS
       
  1974 			const UpsMessage::TPolicyCheckResponse& policyCheckResponseMsg = static_cast<UpsMessage::TPolicyCheckResponse&>(aCFMessage);
       
  1975 			ProcessPolicyCheckResponse(policyCheckResponseMsg);
       
  1976 			return KErrNone;
       
  1977 			}
       
  1978 		  }
       
  1979 		}
       
  1980 	else
       
  1981 	if (TCFDataClient::ERealmId == aCFMessage.MessageId().Realm())
       
  1982 		{
       
  1983 		switch (aCFMessage.MessageId().MessageId())
       
  1984 		  {
       
  1985 		case TCFDataClient::TProvisionConfig::EId :
       
  1986 			{
       
  1987            	// Get a pointer to the UPS Access Point Config structure.  If not present, then UPS is
       
  1988            	// disabled ("short circuited") and iUpsExtension remains set to NULL.
       
  1989            	const  TCFDataClient::TProvisionConfig& provisionMsg = static_cast<TCFDataClient::TProvisionConfig&>(aCFMessage);
       
  1990            	
       
  1991            	iAccessPointConfig.Close();
       
  1992            	iAccessPointConfig.Open(provisionMsg.iConfig);
       
  1993            	
       
  1994 			const Meta::SMetaData* const extension = AccessPointConfig().FindExtension(
       
  1995 			        STypeId::CreateSTypeId(CUPSAccessPointConfigExt::EUPSAccessPointConfigUid, CUPSAccessPointConfigExt::ETypeId));
       
  1996 			if (extension)
       
  1997 				{
       
  1998 				iUpsExtension = const_cast<CUPSAccessPointConfigExt*> (static_cast<const CUPSAccessPointConfigExt*>(extension));
       
  1999 				}
       
  2000 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  2001 			//
       
  2002 			//Store the provision config message,
       
  2003 			//to store the Provision config message
       
  2004 			//which will have TCP Receive window sizes.
       
  2005             StoreProvision(static_cast<TCFDataClient::TProvisionConfig&>(aCFMessage));
       
  2006 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  2007 
       
  2008 			return KErrNone;
       
  2009 	       	}
       
  2010 		  }
       
  2011 		}
       
  2012 	return KErrNotSupported;
       
  2013 	}
       
  2014 
       
  2015 void CUpsTransportFlowShim::SubConnectionError(const Messages::TEBase::TError& aErrorMsg, TUint anOperationMask)
       
  2016 /**
       
  2017 Handle errors from SCpr
       
  2018 
       
  2019 @param aErrorMsg The incoming TError message
       
  2020 @param anOperationMask Pending operations to be error'd.
       
  2021 */
       
  2022 	{
       
  2023 	if (aErrorMsg.iMsgId == UpsMessage::TPolicyCheckRequest::Id())
       
  2024 		{
       
  2025 		// Previously sent TPolicyCheckRequest failed.
       
  2026 		SetPolicyCheckRequestPending(EFalse);
       
  2027 		ProcessDCIdleState();
       
  2028 		}
       
  2029 
       
  2030 	CTransportFlowShim::SubConnectionError(aErrorMsg, anOperationMask);
       
  2031 	}
       
  2032 
       
  2033 TBool CUpsTransportFlowShim::ActivityRunning()
       
  2034 /**
       
  2035 Determine whether we are in the middle of NoBearer or PolicyCheckRequest processing.
       
  2036 
       
  2037 In other words, we are waiting for a response from a previously transmitted TNoBearer
       
  2038 or TPolicyCheckRequest.
       
  2039 
       
  2040 @return ETrue if in the middle of one of this activity, else EFalse.
       
  2041 */
       
  2042 	{
       
  2043 	return PolicyCheckRequestPending() || CTransportFlowShim::ActivityRunning();
       
  2044 	}
       
  2045 
       
  2046 #endif //f_NETWORKING_UPS
       
  2047 
       
  2048 
       
  2049 
       
  2050 //Register the class variable
       
  2051 START_ATTRIBUTE_TABLE(CSAPSetOpt,CSAPSetOpt::EUid, CSAPSetOpt::ETypeId)
       
  2052 END_ATTRIBUTE_TABLE()
       
  2053 
       
  2054 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  2055 //Set the protocol options
       
  2056 void CTransportFlowShim::SetProtocolOptions()
       
  2057 	{
       
  2058 	if(iProvider && iProtocolOptions)
       
  2059 		{
       
  2060 		for(TInt iter = 0; iter < iProtocolOptions->iOption.Count(); iter++)
       
  2061 			{
       
  2062    	    	TPtr8 optionDesProtOptVal( (TUint8*)&(iProtocolOptions->iOption[iter].iOptionValue), sizeof(TUint), sizeof(TUint) );
       
  2063 			iProvider->SetOption(iProtocolOptions->iOption[iter].iOptionName,iProtocolOptions->iOption[iter].iOptionLevel, optionDesProtOptVal);
       
  2064 			}
       
  2065 		}
       
  2066 	}
       
  2067 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  2068 
       
  2069 EXPORT_C CSAPSetOpt::CSAPSetOpt()
       
  2070 	{
       
  2071 	}
       
  2072 
       
  2073 CSAPSetOpt::~CSAPSetOpt()
       
  2074 	{
       
  2075 	//Free the RArray resources.
       
  2076 	iOption.Close();
       
  2077 	}
       
  2078 
       
  2079 //Add the option to the RArray variable
       
  2080 EXPORT_C void CSAPSetOpt::AddProtocolOptionL(TUint aOptionName, TUint aOptionLevel, TUint aOptionValue)
       
  2081 	{
       
  2082 	TProtocolOption opt;
       
  2083 	opt.iOptionName = aOptionName;
       
  2084 	opt.iOptionLevel = aOptionLevel;
       
  2085 	opt.iOptionValue = aOptionValue;
       
  2086 	iOption.AppendL(opt);
       
  2087 	}
       
  2088 
       
  2089 //Update the value for an option
       
  2090 EXPORT_C void CSAPSetOpt::UpdateProtocolOption(TUint aOptionName, TUint aOptionLevel, TUint aOptionValue)
       
  2091 	{
       
  2092 	for(TInt i = 0; i < iOption.Count(); i++)
       
  2093 		if((iOption[i].iOptionName == aOptionName) && (iOption[i].iOptionLevel == aOptionLevel))
       
  2094 			iOption[i].iOptionValue = aOptionValue;
       
  2095 	}
       
  2096 
       
  2097 
       
  2098