--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_connLegacy.cpp Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,1261 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "ss_connlegacy.h"
+#include <ss_std.h>
+#include "ss_connstates.h"
+#include <comms-infras/sockmes.h>
+#include <cdblen.h>
+#include <ss_glob.h>
+#include <comms-infras/ss_log.h>
+#include "SS_rslv.H"
+#include <ss_sock.h>
+#include <comms-infras/ss_sapshim.h>
+#include <comms-infras/ss_connsettings.h>
+#include "ss_subconn.h"
+#include <comms-infras/esockmessages.h>
+
+#include <comms-infras/ss_datamonitoringprovider.h>
+#include <comms-infras/nifif.h>
+#include "SS_conn.H"
+#include <comms-infras/ss_datamon_apiext.h>
+#include <comms-infras/ss_roles.h>
+#include <commdbconnpref.h> //TCommDbConnPref
+#include <comms-infras/ss_nodemessages_serviceprovider.h>
+#include <elements/nm_messages_child.h>
+#include "ss_internal_activities.h"
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_ESockSSockscnLgc, "ESockSSockscnLgc");
+#endif
+
+using namespace ESock;
+using namespace Messages;
+using namespace MeshMachine;
+using namespace Factories;
+using namespace Den;
+
+
+//************************************* old stuff ********************************//
+
+
+
+//const TInt KNumberOfEmulatedSubConnections = 2;
+
+const Factories::TAnyFn AConnectionLegacy::iInterfaceVTableF[] =
+ {
+ (Factories::TAnyFn)1,
+ (Factories::TAnyFn)(TFactoryNotify<AConnectionLegacy>::Notification)
+ };
+
+AConnectionLegacy::~AConnectionLegacy()
+ {
+ TSubConnectionEvent* subConnectionEvent;
+ while (iSubConnectionEventQueue.Deque(subConnectionEvent))
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tDequeuing and deleting subconnection event(%08x)"), this, subConnectionEvent));
+ delete subConnectionEvent;
+ subConnectionEvent = NULL;
+ }
+
+ iConnectionSocketBuf.Close();
+ iConnectionClientBuf.Close();
+ iConnectionInfoPtrArray.ResetAndDestroy();
+ FinalCompleteAllBlockedMessages(KErrCancel);
+ for (TInt i = 0; i < iSubConnections.Count(); ++i)
+ {
+ iSubConnections.Close();
+ }
+ }
+
+void AConnectionLegacy::CancelProviderRequests()
+ {
+// CancelServiceChangeNotification();
+ }
+
+void AConnectionLegacy::FinalCompleteAllBlockedMessages(TInt /* aReason */)
+ {
+ // If the all interface notification worker is running then post a
+ // destroy to it.
+ if(!iAllInterfaceNotificationWorker.IsNull())
+ {
+ TNodeCtxId dest(ECFActivityConnectionAllInterfaceNotification, iAllInterfaceNotificationWorker);
+ RNodeInterface::OpenPostMessageClose(iConnection.Id(), dest, TEBase::TCancel().CRef());
+ iAllInterfaceNotificationWorker.SetNull();
+ }
+ }
+
+
+
+namespace ESock
+{
+class XConnectionFactoryAPQuery : public Factories::MFactoryQuery
+ {
+public:
+ XConnectionFactoryAPQuery(TInt aAp)
+ :iAp( aAp ) {}
+
+protected:
+ TInt iAp;
+
+public:
+ virtual TMatchResult Match(TFactoryObjectInfo& aConnectionInfo);
+ };
+}
+
+MFactoryQuery::TMatchResult XConnectionFactoryAPQuery::Match(TFactoryObjectInfo& aConnectionInfo)
+ {
+ CConnectionProviderBase* connProv = static_cast<CConnectionProviderBase*>(aConnectionInfo.iInfo.iFactoryObject);
+ return connProv->ProviderInfo().APId() == iAp ? MFactoryQuery::EMatch : MFactoryQuery::EContinue;
+ }
+
+
+static const TUid K_CIPProtoConnectionProviderFactory_iUid = {0x10281DD3};
+
+void AConnectionLegacy::CompleteAttachL(ESock::TSelectionPrefs& aPrefs)
+ {
+ //We have built the new top (legacy) Cpr and now we need to make sure that
+ //it is properly joined to the layer directly below it (i.e. IpProto).
+ TConnPref& cp = aPrefs.Prefs();
+ __ASSERT_DEBUG(cp.ExtensionId()==TConnPref::EConnPrefCommDb, User::Panic(KSpecAssert_ESockSSockscnLgc, 1)); //Must be legacy now
+
+ __ASSERT_DEBUG(iConnection.ServiceProvider(), User::Panic(KSpecAssert_ESockSSockscnLgc, 2)); //The CConnection has been already joined
+ RNodeInterface* sp = iConnection.ServiceProvider();
+ Messages::ANode& connProvNode = sp->RecipientId().Node();
+ MeshMachine::AMMNodeBase* cpr = reinterpret_cast<MeshMachine::AMMNodeBase*>(connProvNode.FetchNodeInterfaceL(AMMNodeBase::KInterfaceId));
+ __ASSERT_DEBUG(cpr->GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider))==NULL, User::Panic(KSpecAssert_ESockSSockscnLgc, 3)); //This is why we are "legacy"
+
+ CConnectionFactoryContainer& container = *static_cast<CPlayer&>(iConnection.Player()).SockManGlobals()->iConnectionFactories;
+ CCommsFactoryBase* factory = static_cast<CCommsFactoryBase*>(container.FindFactory(K_CIPProtoConnectionProviderFactory_iUid));
+ User::LeaveIfError(factory? KErrNone : KErrArgument);
+
+ XConnectionFactoryAPQuery query(static_cast<const TCommDbConnPref&>(cp).IapId());
+ CConnectionProviderBase* ipProtoCpr = static_cast<CConnectionProviderBase*>(factory->Find(query));
+ User::LeaveIfError(ipProtoCpr? KErrNone : KErrArgument);
+
+ cpr->AddClientL(ipProtoCpr->Id(),TClientType(TCFClientType::EServProvider, TCFClientType::EActive));
+ TUint clientFlags = 0;
+ if (aPrefs.Flags()&TSelectionPrefs::EMonitor)
+ {
+ __ASSERT_DEBUG(iConnection.IsMonitor(), User::Panic(KSpecAssert_ESockSSockscnLgc, 4)); //Well, we are attaching as a monitor, must be consistent!
+ clientFlags = TCFClientType::EMonitor;
+ }
+
+ TRAPD(error,ipProtoCpr->AddClientL(cpr->Id(),TClientType(TCFClientType::ECtrl,clientFlags)));
+ if (error!=KErrNone)
+ {
+ iConnection.ServiceProvider()->PostMessage(ipProtoCpr->Id(), TEChild::TLeft().CRef());
+ User::Leave(error);
+ }
+
+ iConnection.ServiceProvider()->SetFlags(TCFClientType::EStarted);
+ }
+
+/**
+Process RConnection messages
+@exception Leaves on any error processing the request
+*/
+TInt AConnectionLegacy::ProcessMessageL(const RMessage2& aMessage)
+ {
+ LOG_DETAILED( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy %08x:\tCommand %d"), this, aMessage.Function()) );
+ switch (aMessage.Function())
+ {
+ case ECNAllSubConnectionNotification:
+ AllSubConnectionNotificationL();
+ break;
+
+ case ECNCancelAllSubConnectionNotification:
+ CancelAllSubConnectionNotification();
+ break;
+
+ case ECNEnumerateSubConnections:
+ EnumerateSubConnectionsL(iConnection.SafeMessage());
+ break;
+
+ case ECNAllInterfaceNotification:
+ AllInterfaceNotificationL(aMessage);
+ break;
+
+ case ECNCancelAllInterfaceNotification:
+ CancelAllInterfaceNotification();
+ break;
+
+ case ECNGetConnectionInfo:
+ GetConnectionInfoL(aMessage);
+ break;
+
+ case ECNServiceChangeNotification:
+ RequestServiceChangeNotificationL(iConnection.SafeMessage());
+ break;
+
+ case ECNCancelServiceChangeNotification:
+ CancelServiceChangeNotification(iConnection.SafeMessage());
+ break;
+
+ case ECNGetIntSetting:
+ GetIntSettingL(iConnection.SafeMessage());
+ break;
+
+ case ECNGetBoolSetting:
+ GetBoolSettingL(iConnection.SafeMessage());
+ break;
+
+ case ECNGetDes8Setting:
+ GetDes8SettingL(iConnection.SafeMessage());
+ break;
+
+ case ECNGetDes16Setting:
+ GetDes16SettingL(iConnection.SafeMessage());
+ break;
+
+ case ECNGetLongDesSetting:
+ GetLongDesSettingL(iConnection.SafeMessage());
+ break;
+
+ case ESCPSProgressNotification:
+ iConnection.SetReturn(KErrNotSupported);
+ break;
+
+ case ESCPSCancelProgressNotification:
+ break;
+
+ case ESCPSDataTransferred:
+ DataTransferredL(iConnection.SafeMessage());
+ break;
+
+ case ESCPSDataTransferredCancel:
+ break;
+
+ case ESCPSDataSentNotificationRequest:
+ DataSentNotificationRequestL(iConnection.SafeMessage());
+ break;
+
+ case ESCPSDataSentNotificationCancel:
+ DataSentNotificationCancel(iConnection.SafeMessage());
+ break;
+
+ case ESCPSDataReceivedNotificationRequest:
+ DataReceivedNotificationRequestL(iConnection.SafeMessage());
+ break;
+
+ case ESCPSDataReceivedNotificationCancel:
+ DataReceivedNotificationCancel(iConnection.SafeMessage());
+ break;
+
+ case ESCPSIsSubConnectionActiveRequest:
+ IsSubConnectionActiveRequestL(iConnection.SafeMessage());
+ break;
+
+ case ESCPSIsSubConnectionActiveCancel:
+ IsSubConnectionActiveCancel(iConnection.SafeMessage());
+ break;
+
+ case ESCPSGetSubConnectionInfo:
+ GetSubConnectionInfoL(iConnection.SafeMessage());
+ break;
+
+ default:
+ iConnection.SetReturn(KErrNotSupported);
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("CConnectionLegacy(%08x)::ProcessMessageL - unsupported IPC %d received"), this, aMessage.Function()));
+ }
+ return KErrNone;
+ }
+
+/**
+Control method to send a general command towards the interface.
+*/
+void AConnectionLegacy::ControlL(TUint aOptionName, TUint aMessageId)
+ {
+ if (aMessageId == KCOLConnection)
+ {
+ switch(aOptionName)
+ {
+ case KCoEnumerateConnectionClients:
+ EnumerateConnectionClientsL();
+ return;
+ case KCoGetConnectionClientInfo:
+ GetConnectionClientInfoL();
+ return;
+ case KCoEnumerateConnectionSockets:
+ EnumerateConnectionSocketsL();
+ return;
+ case KCoGetConnectionSocketInfo:
+ GetConnectionSocketInfoL();
+ return;
+ default:
+ User::Leave(KErrNotSupported);
+ }
+ }
+ }
+
+
+/**
+Get the number of currently active subconnections
+@see RConnection::EnumerateSubConnections for notes on the difference in behaviour between this function and EnumerateConnectionsL()
+*/
+void AConnectionLegacy::EnumerateSubConnectionsL(const Den::RSafeMessage& aMessage)
+ {
+ RNodeInterface* sp = iConnection.ServiceProvider();
+ if(!sp || !(sp->Flags() & TCFClientType::EStarted))
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("CConnection (AConnectionLegacy) [this=%08x] EnumerateSubConnectionsL KErrNotReady(-18)"), &iConnection));
+ iConnection.SetReturn(KErrNotReady);
+ return;
+ }
+
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), TLegacyEnumerateSubConnections(aMessage));
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+void AConnectionLegacy::AllInterfaceNotificationL(const RMessage2& aMessage)
+ {
+ if(!iAllInterfaceNotificationMessage.IsNull() || iConnection.ServiceProvider())
+ {
+ iConnection.SetReturn(KErrInUse);
+ return;
+ }
+
+ iAllInterfaceNotificationMessage = aMessage;
+ iConnection.DontCompleteCurrentRequest();
+
+ if(iAllInterfaceNotificationWorker.IsNull())
+ {
+ CAllInterfaceNotificationWorker* worker = new(ELeave) CAllInterfaceNotificationWorker(iConnection);
+ iAllInterfaceNotificationWorker = worker->Id();
+
+ TNodeCtxId dest(ECFActivityConnectionAllInterfaceNotification, iAllInterfaceNotificationWorker);
+ RNodeInterface::OpenPostMessageClose(iConnection.Id(), dest, TCFServiceProvider::TStart().CRef());
+ }
+
+ CompleteAllInterfaceNotificationL(KErrNone);
+ }
+
+void AConnectionLegacy::CompleteAllInterfaceNotificationL(TInt aError)
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy [this=%08x] CompleteAllInterfaceNotificationL message (%08X) with %d"), &iConnection, iAllInterfaceNotificationMessage.Handle(), aError));
+
+ if(!iAllInterfaceNotificationMessage.IsNull())
+ {
+ if(aError == KErrNone)
+ {
+ if(!iNotificationQueue.IsEmpty())
+ {
+ TInterfaceNotification notification;
+ iNotificationQueue.Deque(notification);
+
+ TInterfaceNotificationBuf buf(notification);
+
+ // Write the buffer to the client
+ iAllInterfaceNotificationMessage.WriteL(0, buf);
+ iAllInterfaceNotificationMessage.Complete(KErrNone);
+ iAllInterfaceNotificationMessage = RMessage2();
+ }
+ }
+ else
+ {
+ iAllInterfaceNotificationMessage.Complete(aError);
+ iAllInterfaceNotificationMessage = RMessage2();
+ }
+ }
+ }
+
+void AConnectionLegacy::CancelAllInterfaceNotification()
+ {
+ if(!iAllInterfaceNotificationMessage.IsNull())
+ {
+ iAllInterfaceNotificationMessage.Complete(KErrCancel);
+ }
+ }
+
+void AConnectionLegacy::RequestServiceChangeNotificationL(const Den::RSafeMessage& aMessage)
+ {
+ RNodeInterface* currServiceProvider = iConnection.ServiceProvider();
+ if (!currServiceProvider)
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy [this=%08x] RequestServiceChangeNotificationL KErrNotReady"), &iConnection));
+ iConnection.SetReturn(KErrNotReady);
+ return;
+ }
+
+ if(iServiceChangeNotificationPending)
+ {
+ iConnection.SetReturn(KErrInUse);
+ return;
+ }
+
+ // This message needs to be directed towards the MCpr - Service change notification occurs
+ // during reconnection. We violate the principle of left hand nodes not instructing right
+ // hand nodes. Since this is for legacy support its ok for now. The CPr that implements
+ // the Api is expected to forward this message to its MCpr
+ iServiceChangeNotificationPending = ETrue;
+
+ TCprRequestServiceNotification msg(iConnection.Id(), aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+void AConnectionLegacy::CancelServiceChangeNotification(const Den::RSafeMessage& aMessage)
+ {
+ // This message needs to be directed towards the MCpr - Service change notification occurs
+ // during reconnection. We violate the principle of left hand nodes not instructing right
+ // hand nodes. Since this is for legacy support its ok for now. The CPr that implements
+ // the Api is expected to forward this message to its MCpr
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy [this=%08x] CancelServiceChangeNotification KErrCancel"), &iConnection));
+ const RPointerArray<CNodeActivityBase>& activities = iConnection.Activities();
+ for (TInt i = 0; i < activities.Count(); i++)
+ {
+ if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler)
+ {
+ ConnActivities::CConnLegacyRMessage2Activity* act = static_cast<ConnActivities::CConnLegacyRMessage2Activity*>(activities[i]);
+ if (act->iSafeMessage.Function() == ECNServiceChangeNotification)
+ {
+ act->SetCancelRequest(aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(act->iSafeMessage.Function(), TEBase::TCancel().CRef());
+ iConnection.DontCompleteCurrentRequest();
+ }
+ }
+ }
+ iServiceChangeNotificationPending = EFalse;
+ }
+
+
+/**
+Return information about a single connection that was previously
+enumerated using EnumerateConnectionsL
+
+This is the server-side implementation of the RConnection
+function TInt GetConnectionInfo(TUint aIndex, TDes8& aConnectionInfo).
+*/
+void AConnectionLegacy::GetConnectionInfoL(const RMessage2& aMessage)
+ {
+ TUint index = aMessage.Int0();
+
+ // Make sure the client isn't using an invalid argument (*client* connection numbering starts from 1)
+ if(index == 0)
+ {
+ iConnection.SetReturn(KErrArgument);
+ return;
+ }
+
+ // Make sure the client isn't trying to access a connection that doesn't exist
+ if(index > static_cast<TUint>(iConnectionInfoPtrArray.Count()))
+ {
+ iConnection.SetReturn(KErrNotFound);
+ return;
+ }
+
+ index = index - 1; // alter the client-provided index (indexed from one) to act as a index for the array (indexed from zero)
+
+ // check the client argument's version to see which one it's using
+ TConnArgBase clientArg;
+ TPckg<TConnArgBase> argPckg(clientArg);
+ aMessage.ReadL(1, argPckg);
+ TUint8 clientVersion = clientArg.Version();
+
+ // Translate between versions of TConnectionInfo depending on what client passes in
+ __ASSERT_DEBUG(iConnectionInfoPtrArray[index]->Version() == KConnArgVersion2, User::Panic(KSpecAssert_ESockSSockscnLgc, 5)); // check that the connection provider has put TConnectionInfoV2's in the queue
+
+ if(clientVersion == KConnArgVersion1)
+ {
+ TConnectionInfo connectionInfoV1;
+ connectionInfoV1.iIapId = iConnectionInfoPtrArray[index]->iIapId;
+ connectionInfoV1.iNetId = iConnectionInfoPtrArray[index]->iNetId;
+ TPckg<TConnectionInfo> info(connectionInfoV1);
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Client called GetConnectionInfo (client ver=%d, esock ver=%d), writing [%S](%d bytes) to client side"), clientArg.Version(), iConnectionInfoPtrArray[index]->Version(), &info, info.Size()); )
+
+ aMessage.WriteL(1, info);
+ }
+ else
+ {
+ if(clientVersion == KConnArgVersion2)
+ {
+ // downcast from TConnectionInfo pointer to TConnectionInfoV2 pointer; we can do this safely because the earlier ASSERT() checked that these were TConnectionInfoV2s
+ TPckg<TConnectionInfoV2> info(*(static_cast<TConnectionInfoV2*>(iConnectionInfoPtrArray[index])));
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Client called GetConnectionInfo (client ver=%d, esock ver=%d), writing [%S](%d bytes) to client side"), clientArg.Version(), iConnectionInfoPtrArray[index]->Version(), &info, info.Size()); )
+ aMessage.WriteL(1, info);
+ }
+ else
+ {
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Invalid version of argument to GetConnectionInfo (client ver=%d, esock ver=%d)"), clientArg.Version(), iConnectionInfoPtrArray[index]->Version()); )
+ iConnection.SetReturn(KErrArgument);
+ }
+ }
+ }
+
+
+/**
+Extract a single enumeration information element from a buffer of elements
+
+@param aBuffer the buffer from which to extract the information element
+@param aCount the total number of elements in the buffer
+@param aSize the size of each information element
+@param aIndex the position of the element to retrieve in the buffer. Index is 1-based.
+@param aPckg the TPckg<> in which to return the information element
+@exception leaves with KErrOverflow if the index given is past the end of the buffer
+*/
+void AConnectionLegacy::ExtractEnumInfoL(RBuf8& aBuffer, TUint aCount, TInt aSize, TUint aIndex, TDes8& aPckg)
+ {
+ if (aBuffer.Length() == 0)
+ {
+ LOG( ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy %08x ExtractEnumInfoL KErrNotReady"), this) );
+ User::Leave(KErrNotReady);
+ }
+ else if (aIndex < 1)
+ {
+ User::Leave(KErrArgument);
+ }
+ else if (aIndex > aCount)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ __ASSERT_DEBUG((TUint) aBuffer.Length() == (aCount * aSize), User::Panic(KSpecAssert_ESockSSockscnLgc, 6));
+
+ const TUint8* ptr = aBuffer.Ptr();
+
+ TInt start = aSize * (aIndex-1);
+ ptr += start;
+
+ aPckg.Copy(ptr, aSize);
+ }
+
+/**
+Gather information on the number of clients of a particular connection
+
+This is the server-side implementation of the RConnection
+function TInt EnumerateConnectionClients(TUint aIndex, TUint& aCount).
+*/
+void AConnectionLegacy::EnumerateConnectionClientsL()
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy::EnumerateConnectionClientsL()")));
+ // Cover the remote case that another client thread is already enumerating the connection in a similar way - when it all
+ // completed synchronously in the same thread there was no possibility of this problem. Attempting the same queue behaviour
+ // here seems pointless: it's a very rare case of a rare case of a deprecated API which was never documented as working
+ // that way. So instead we complete the client with KErrBusy
+ if(!iEnumConnMsg.IsNull())
+ {
+ User::Leave(KErrServerBusy);
+ }
+
+ iConnectionClientCount = 0;
+ iDPEnumCount = &iConnectionClientCount;
+ iConnectionClientBuf.Close();
+
+ iDPEnumBuf = &iConnectionClientBuf;
+ RequestDataPlaneEnumerationL(EAll);
+ }
+
+
+/**
+Returns information about a single connection client that was previously
+enumerated using EnumerateConnectionClientsL
+
+This is the server-side implementation of the RConnection
+function TInt GetConnectionClientInfo(TUint aIndex, TDes8& aClientInfo).
+*/
+void AConnectionLegacy::GetConnectionClientInfoL()
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy::GetConnectionClientInfoL()")));
+ TConnectionGetClientInfoArg args;
+ TUint8 ourVersion = args.Version();
+
+ const RSafeMessage& message(iConnection.SafeMessage());
+ TPckg<TConnectionGetClientInfoArg> argsPckg(args);
+ message.ReadL(2, argsPckg);
+
+ // check that the client argument's version is the same as the one we're using
+ if(args.Version() != ourVersion)
+ {
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Invalid version of argument to GetConnectionClientInfo (client ver=%d, esock ver=%d)"), args.Version(), ourVersion) );
+ User::Leave(KErrArgument);
+ }
+
+ TConnectionClientInfo clientInfo;
+ TPckg<TConnectionClientInfo> info(clientInfo);
+ ExtractEnumInfoL(iConnectionClientBuf, iConnectionClientCount, sizeof(TConnectionClientInfo), argsPckg().iIndex, info);
+
+ argsPckg().iClientInfo = info();
+ message.WriteL(2, argsPckg);
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy [this=%08x] GetConnectionClientInfoL message (%08X) with KErrNone"), &iConnection, message.Handle()));
+ message.Complete(KErrNone);
+ }
+
+/**
+Gather information on the number of sockets of a particular connection
+
+This is the server-side implementation of the RConnection
+function TInt EnumerateConnectionSockets(TUint aIndex, TUint& aCount).
+*/
+void AConnectionLegacy::EnumerateConnectionSocketsL()
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy::EnumerateConnectionSocketsL")));
+ // Cover the remote case that another client thread is already enumerating the connection in a similar way - when it all
+ // completed synchronously in the same thread there was no possibility of this problem. Attempting the same queue behaviour
+ // here seems pointless: it's a very rare case of a rare case of a deprecated API which was never documented as working
+ // that way. So instead we complete the client with KErrServerBusy
+ if(!iEnumConnMsg.IsNull())
+ {
+ User::Leave(KErrServerBusy);
+ }
+
+ // delete any previous connection client enumeration info
+ iConnectionSocketCount = 0;
+ iDPEnumCount = &iConnectionSocketCount;
+ iConnectionSocketBuf.Close();
+
+ iDPEnumBuf = &iConnectionSocketBuf;
+ RequestDataPlaneEnumerationL(ESocket);
+ }
+
+/**
+Returns information about a socket associated with this connection that has
+been previously enumerated using EnumerateConnectionSocketsL
+
+This is the server-side implementation of the RConnection
+function TInt GetConnectionSocketInfo(TUint aIndex, TDes8& aSockettInfo).
+*/
+void AConnectionLegacy::GetConnectionSocketInfoL()
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy::GetConnectionSocketInfoL()")));
+ TConnectionGetSocketInfoArg args;
+ TUint8 ourVersion = args.Version();
+
+ const RSafeMessage& message(iConnection.SafeMessage());
+ TPckg<TConnectionGetSocketInfoArg> argsPckg(args);
+ message.ReadL(2, argsPckg);
+
+ if(args.Version() != ourVersion)
+ {
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Invalid version of argument to GetConnectionSocketInfo (client ver=%d, esock ver=%d)"), args.Version(), ourVersion) );
+ User::Leave(KErrArgument);
+ }
+
+ TConnectionSocketInfo socketInfo;
+ TPckg<TConnectionSocketInfo> info(socketInfo);
+ ExtractEnumInfoL(iConnectionSocketBuf, iConnectionSocketCount, sizeof(TConnectionSocketInfo), argsPckg().iIndex, info);
+
+ argsPckg().iSocketInfo = info();
+ message.WriteL(2, argsPckg);
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("AConnectionLegacy [this=%08x] GetConnectionSocketInfoL message (%08X) with KErrNone"), &iConnection, message.Handle()));
+ message.Complete(KErrNone);
+ }
+
+/**
+Requests the Data plane to enumerate its subsessions checking for flows belonging to the set of SCPR ids
+furnished in this request, returning either socket or client info. This is specifically to support the
+legacy enumerations; no expectation that a more general scheme will ever be needed
+*/
+void AConnectionLegacy::RequestDataPlaneEnumerationL(TLegacyConnEnumClients aClientType)
+ {
+ iEnumConnSockCandidateSCPRs.Reset();
+ TConnectionEnumArg args;
+ TUint8 ourVersion = args.Version();
+
+ TPckg<TConnectionEnumArg> argsPckg(args);
+ const RSafeMessage& message(iConnection.SafeMessage());
+ message.ReadL(2, argsPckg);
+
+ if(args.Version() != ourVersion)
+ {
+ LOG( ESockLog::Printf(KESockConnectionTag, _L("AConnectionLegacy: Invalid version of argument to EnumerateConnectionSockets (client ver=%d, esock ver=%d)"), args.Version(), ourVersion) );
+ User::Leave(KErrArgument);
+ }
+
+ TInt index = args.iIndex;
+
+ if(index <= 0 || index > iConnectionInfoPtrArray.Count())
+ {
+ User::Leave(KErrArgument);
+ }
+
+ index -= 1; // convert from client index (starting from 1) to server index (starting from 0)
+
+ TSourcedConnectionInfo* connInfo;
+ connInfo = iConnectionInfoPtrArray[index];
+
+ /**
+ For each CSockSubSession which is a connection, check if it uses the cpr identified in conninfo. If so add that connection as
+ a client (for EAll) and add any scprs to the scpr candidate list to be sent to the data plane.
+
+ Then query the data plane for CSockets and CHostResolvers. These are matched to the connection by the scprs in the candidate list
+ */
+ CPlayer::TSubSessionContainer& subSess = iConnection.Player().SubSessions();
+ for(TInt idx = subSess.Count() - 1; idx >=0; --idx)
+ {
+ TBool isClient = EFalse;
+
+ const CSockSubSession* ss = static_cast<const CSockSubSession*>(subSess[idx]);
+ if(ss->Type().iType == TCFSubSessInfo::EConnection)
+ {
+ const CConnection* conn = static_cast<const CConnection*>(ss);
+
+ RNodeInterface* ipcprItf = conn->ServiceProvider();
+
+ if(ipcprItf != NULL)
+ {
+ ACFMMNodeIdBase& ipcpr = static_cast<ACFMMNodeIdBase&>(ipcprItf->RecipientId().Node());
+
+ RNodeInterface* lowerCprItf = ipcpr.ServiceProvider();
+ while (lowerCprItf)
+ {
+ if(lowerCprItf->RecipientId() == connInfo->Provider())
+ {
+ isClient = ETrue;
+ break;
+ }
+
+ ACFMMNodeIdBase& lowerCpr = static_cast<ACFMMNodeIdBase&>(lowerCprItf->RecipientId().Node());
+ lowerCprItf = lowerCpr.ServiceProvider();
+ }
+
+ if (isClient)
+ {
+ // Add to client list
+ if (aClientType == EAll)
+ {
+ TConnectionClientInfo info;
+ TUidType uidType;
+ ss->GetOwnerInfo(info.iProcessId, uidType, info.iThreadId);
+ info.iUid = uidType.MostDerived();
+ RBuf8& resDes = *iDPEnumBuf;
+
+ if (!AConnectionLegacy::DoesConnectionInfoExist(resDes, info))
+ {
+ const TUint KEntrySize = sizeof(TConnectionClientInfo);
+ if (resDes.Length() + KEntrySize > resDes.MaxLength())
+ {
+ resDes.ReAllocL(resDes.Length() + KEntrySize);
+ }
+
+ resDes.Append(reinterpret_cast<TUint8*>(&info), sizeof(info));
+ ++(*iDPEnumCount);
+ }
+ }
+
+ // Build the list of candidate SCPR ids for the data plane to check against
+ TClientIter<TDefaultClientMatchPolicy> scprIter = ipcpr.GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, 0));
+ RNodeInterface* scpr;
+ while((scpr = scprIter++) != NULL)
+ {
+ iEnumConnSockCandidateSCPRs.AppendL(scpr->RecipientId());
+ }
+ }
+ }
+ }
+ }
+
+ if(!iEnumConnSockCandidateSCPRs.Count())
+ {
+ // Failed to find the lower CPR; most likely it was torn down since the enumeration
+ User::Leave(KErrNotReady);
+ }
+
+ iEnumConnMsg.Adopt(static_cast<Den::RSafeMessage&>(const_cast<RSafeMessage&>(iConnection.SafeMessage())));
+
+ RNodeInterface::OpenPostMessageClose(iConnection.Id(), SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EDataPlane)),
+ TLegacyConnectionEnumRequest(iEnumConnSockCandidateSCPRs, aClientType));
+ }
+
+/**
+Called when the Data plane returns the result of a flow enumeration, requested through RequestDataPlaneEnumerationL()
+*/
+void AConnectionLegacy::CompleteDataPlaneEnumeration(const TNodeId& aPeer, TInt aCount, HBufC8* aInfo, TInt aError)
+ {
+ iEnumConnSockCandidateSCPRs.Reset();
+ if(aError == KErrNone)
+ {
+ __ASSERT_DEBUG(iDPEnumBuf, User::Panic(KSpecAssert_ESockSSockscnLgc, 7));
+
+ /**
+ Merge the results from the dataplane with the results from
+ this plane if we are enumerating all connection clients.
+ */
+ if (iEnumConnMsg.Int1() == KCoEnumerateConnectionClients)
+ {
+ RBuf8& resDes = *iDPEnumBuf;
+ TConnectionClientInfo info;
+ TPckg<TConnectionClientInfo> des(info);
+
+ const TUint KEntrySize = sizeof(TConnectionClientInfo);
+ ASSERT((aCount * KEntrySize) == aInfo->Length());
+ const TUint8* ptr = aInfo->Ptr();
+ for (TInt i = 0; i < aCount && aError == KErrNone; i++)
+ {
+ des.Copy(ptr, KEntrySize);
+ if (!DoesConnectionInfoExist(resDes, info))
+ {
+ aError = resDes.ReAlloc(resDes.Length()+KEntrySize);
+ if (aError == KErrNone)
+ {
+ resDes.Append(des);
+ (*iDPEnumCount)++;
+ }
+ }
+ ptr += KEntrySize;
+ }
+ }
+ else
+ {
+ *iDPEnumCount += aCount;
+ aError = iDPEnumBuf->ReAlloc(iDPEnumBuf->Length() + aInfo->Length());
+ iDPEnumBuf->Append(*aInfo);
+ }
+ }
+ if(aError == KErrNone)
+ {
+ TConnectionEnumArg args;
+ args.iCount = *iDPEnumCount;
+ TPckg<TConnectionEnumArg> argsPckg(args);
+ aError = iEnumConnMsg.Read(2, argsPckg);
+ if (aError == KErrNone)
+ {
+
+ argsPckg().iCount = *iDPEnumCount;
+ aError = iEnumConnMsg.Write(2, argsPckg);
+ }
+ }
+
+ iEnumConnMsg.Complete(aError);
+ THeapSwitcher switcher(SockManGlobals::Get()->SelfWorker()->PitBoss(), aPeer);
+ delete aInfo;
+ }
+
+
+/**
+Retrieve a TBool parameter setting.
+*/
+void AConnectionLegacy::GetBoolSettingL(const Den::RSafeMessage& aMessage)
+ {
+ TMCprGetConnectionSetting msg(TMCprGetConnectionSetting::EBoolSetting, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+/**
+Retrieve a TUint32 parameter setting.
+*/
+void AConnectionLegacy::GetIntSettingL(const Den::RSafeMessage& aMessage)
+ {
+ TMCprGetConnectionSetting msg(TMCprGetConnectionSetting::EIntSetting, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+/**
+Retrieve a TDes8 parameter setting.
+*/
+void AConnectionLegacy::GetDes8SettingL(const Den::RSafeMessage& aMessage)
+ {
+ TMCprGetConnectionSetting msg(TMCprGetConnectionSetting::EDes8Setting, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+/**
+Retrieve a TDes16 parameter setting.
+*/
+void AConnectionLegacy::GetDes16SettingL(const Den::RSafeMessage& aMessage)
+ {
+ TMCprGetConnectionSetting msg(TMCprGetConnectionSetting::EDes16Setting, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+/**
+Retrieve a Long TDes parameter setting.
+*/
+void AConnectionLegacy::GetLongDesSettingL(const Den::RSafeMessage& aMessage)
+ {
+ TMCprGetConnectionSetting msg(TMCprGetConnectionSetting::ELongDesSetting, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+
+void AConnectionLegacy::InterfaceStateChangeNotification(TDesC8& /*aInfo*/)
+ {
+ //[399TODO] implement InterfaceStateChangeNotification
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("TODO: implement InterfaceStateChangeNotification - KErrNotSupported")));
+#if TODO_IMPLEMENT_THIS
+ TInterfaceNotification& interfaceNotification = ((TInterfaceNotificationBuf&)aInfo)();
+
+ if(iAllInterfaceNotificationMessage.IsNull())
+ {
+ iInterfaceChangeQueue.Enque(interfaceNotification);
+ return;
+ }
+ else // request is outstanding
+ {
+ if(!iInterfaceChangeQueue.IsEmpty())
+ {
+ // can this situation ever happen?
+ // - new requests fullfilled from queue before becoming outstanding
+ // - no queued items when request outstanding
+
+ // But in case we do...
+ // should we get oldest change first in case this new one overwrites it
+ iInterfaceChangeQueue.Enque(interfaceNotification);
+ iInterfaceChangeQueue.Deque(interfaceNotification);
+ }
+
+ TInt ret = iAllInterfaceNotificationMessage.Write(0, aInfo);
+ CompleteMessage(iAllInterfaceNotificationMessage, ret);
+ }
+#endif
+ }
+
+void AConnectionLegacy::SubConnectionEvent(const TSubConnectionEvent& aSubConnectionEvent)
+ {
+ // Pass the message onto the client if possible, or buffer if necessary
+ if(!iAllSubConnectionNotificationMessage.IsNull())
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tdelivering new subconnection event to client (subconnection id: %d, event: %d)"), this, aSubConnectionEvent.iSubConnectionUniqueId, aSubConnectionEvent.iEventType));
+
+ TPtrC8 tempDes(reinterpret_cast<const TUint8*>(&aSubConnectionEvent), aSubConnectionEvent.Length());
+ TSubConnectionNotificationBuf subConnectionEventBuf(tempDes);
+ TInt ret = iAllSubConnectionNotificationMessage.Write(0, subConnectionEventBuf);
+ iConnection.CompleteMessage(iAllSubConnectionNotificationMessage,ret);
+ }
+ else // no outstanding client messages - just buffer it
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tbuffering new subconnection event (subconnection id: %d, event: %d)"), this, aSubConnectionEvent.iSubConnectionUniqueId, aSubConnectionEvent.iEventType));
+
+ // Create copy of event on heap
+ TSubConnectionEvent* subConnectionEvent = 0;
+ TRAPD(ret, subConnectionEvent = aSubConnectionEvent.CloneL());
+
+ if(ret) // if there's an error, write a message to the log - not much else we can do
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tERROR - could not enque new subconnection event, error %d (subconnection id: %d, event: %d)"), this, ret, aSubConnectionEvent.iSubConnectionUniqueId, aSubConnectionEvent.iEventType));
+ }
+ else
+ {
+ if (iSubConnectionEventQueue.IsFull())
+ {
+ TSubConnectionEvent*& oldestSubConnectionEvent = iSubConnectionEventQueue.GetTheOldestElem();
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tSubConnectionEvent - removing oldest subconnection event: %08x)"), this, oldestSubConnectionEvent));
+ delete oldestSubConnectionEvent;
+ }
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tSubConnectionEvent - enquing new subconnection event: %08x)"), this, subConnectionEvent));
+ iSubConnectionEventQueue.Enque(subConnectionEvent);
+ }
+ }
+ }
+
+void AConnectionLegacy::AllSubConnectionNotificationL()
+/**
+Request for notification of subconnection events
+@exception Leaves with KErrInUse if there is already an outstanding RMessage for all subconnection notification
+*/
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tClient requested all subconnection notification..."), this));
+
+ if(!iAllSubConnectionNotificationMessage.IsNull())
+ {
+ iConnection.SetReturn(KErrInUse);
+ return;
+ }
+
+ if(iSubConnectionEventQueue.IsEmpty()) // if there is nothing in the queue, keep the RMessage
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection[%08x]:\tqueueing request."), this));
+ iAllSubConnectionNotificationMessage = iConnection.Message();
+ iConnection.DontCompleteCurrentRequest();
+ }
+ else // otherwise, send back the first item in the queue
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection[%08x]:\tsending back first event from queue."), this));
+
+ TSubConnectionEvent* subConnectionEvent = NULL;
+ iSubConnectionEventQueue.Deque(subConnectionEvent);
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tAllSubConnectionNotificationL - dequing subconnection event: %08x)"), this, subConnectionEvent));
+ TPtrC8 tempDes(reinterpret_cast<const TUint8*>(subConnectionEvent), subConnectionEvent->Length());
+ TSubConnectionNotificationBuf subConnectionEventBuf(tempDes);
+ TInt err = iConnection.Message().Write(0, subConnectionEventBuf);
+
+ // Delete original copy of event from heap
+ delete subConnectionEvent;
+ subConnectionEvent=NULL;
+
+ if(err != KErrNone)
+ {
+ iConnection.SetReturn(err);
+ }
+ }
+ }
+
+void AConnectionLegacy::CancelAllSubConnectionNotification()
+/**
+Complete any outstanding subconnection notification message
+*/
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tClient cancelled all subconnection notification"), this));
+ iDeferredSubConnectionNotificationEnable = EFalse; // Just in case
+ iConnection.CompleteMessage(iAllSubConnectionNotificationMessage, KErrCancel);
+ }
+
+void AConnectionLegacy::GetSubConnectionInfoL(const Den::RSafeMessage& aMessage)
+ {
+ RNodeInterface* sp = iConnection.ServiceProvider();
+ if(!sp)
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag, _L8("CConnection (AConnectionLegacy) [this=%08x] GetSubConnectionInfo KErrNotReady"), &iConnection));
+ iConnection.SetReturn(KErrNotReady);
+ return;
+ }
+
+ TInt subConnIdx = static_cast<TInt>(aMessage.Int0());
+
+ // Find the size of the client's descriptor
+ TInt sizeOfSubConnInfo = aMessage.GetDesLengthL(1);
+
+ // Create an appropriately sized descriptor server-side
+ HBufC8* subConnInfoBuf;
+ subConnInfoBuf = HBufC8::NewL(sizeOfSubConnInfo);
+ CleanupStack::PushL(subConnInfoBuf);
+
+ TPtr8 subConnInfoPtr(subConnInfoBuf->Des());
+
+ // Read the client data across
+ aMessage.ReadL(1, subConnInfoPtr);
+
+ TSubConnectionInfo& subConnInfo = *(reinterpret_cast<TSubConnectionInfo*>(const_cast<TUint8*>(subConnInfoBuf->Ptr())));
+
+ if(subConnInfo.iConnectionType != EConnectionGeneric)
+ {
+ CleanupStack::PopAndDestroy(subConnInfoBuf);
+ iConnection.SetReturn(KErrArgument);
+ return;
+ }
+
+ switch(subConnIdx)
+ {
+ case KNifEMCompatibilityLayerEntireSubConnectionUid:
+ if(subConnInfo.iSubConnectionUniqueId != KNifEMCompatibilityLayerEntireSubConnectionUid &&
+ subConnInfo.iSubConnectionUniqueId != KNifEMCompatibilityLayerFakeSubConnectionId)
+ {
+ CleanupStack::PopAndDestroy(subConnInfoBuf);
+ iConnection.SetReturn(KErrArgument);
+ return;
+ }
+ break;
+
+ case KNifEMCompatibilityLayerFakeSubConnectionId:
+ default:
+ subConnInfo.iSubConnectionUniqueId = KNifEMCompatibilityLayerFakeSubConnectionId;
+
+ break;
+ }
+
+ TLegacyGetSubConnectionInfo msg(iConnection.UniqueId(), subConnInfo, aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+
+ CleanupStack::PopAndDestroy(subConnInfoBuf);
+ }
+
+void AConnectionLegacy::DataTransferredL(const RSafeMessage& aMessage)
+ {
+ TLegacyDataMonitoringTransferredRequest dmReq(iConnection.UniqueId(), aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), dmReq);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+void AConnectionLegacy::DataSentNotificationRequestL(const RSafeMessage& aMessage)
+ {
+ DataMonitoringNotificationRequestL(aMessage, ESent);
+ }
+
+void AConnectionLegacy::DataReceivedNotificationRequestL(const RSafeMessage& aMessage)
+ {
+ DataMonitoringNotificationRequestL(aMessage, EReceived);
+ }
+
+void AConnectionLegacy::DataMonitoringNotificationRequestL(const RSafeMessage& aMessage, TDataMonitoringDirection aDirection)
+ {
+ TLegacyDataMonitoringNotificationRequest dmReq(aDirection, iConnection.UniqueId(), aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), dmReq);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+
+void AConnectionLegacy::DataSentNotificationCancel(const Den::RSafeMessage& aMessage)
+ {
+ DataMonitoringNotificationCancel(aMessage, ESent);
+ }
+
+void AConnectionLegacy::DataReceivedNotificationCancel(const Den::RSafeMessage& aMessage)
+ {
+ DataMonitoringNotificationCancel(aMessage, EReceived);
+ }
+
+void AConnectionLegacy::DataMonitoringNotificationCancel(const Den::RSafeMessage& aMessage, TDataMonitoringDirection aDirection)
+ {
+ const RPointerArray<CNodeActivityBase>& activities = iConnection.Activities();
+ TBool cancelled = EFalse;
+ for (TInt i = 0; i < activities.Count(); i++)
+ {
+ if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler)
+ {
+ ConnActivities::CConnLegacyRMessage2Activity* act = static_cast<ConnActivities::CConnLegacyRMessage2Activity*>(activities[i]);
+
+ ASSERT(act->Message().IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId)));
+ ESock::TCFSigLegacyRMessage2Ext& msg = static_cast<TCFSigLegacyRMessage2Ext&>(act->Message());
+
+ if (act->iSafeMessage.Function() == ESCPSDataSentNotificationRequest
+ || act->iSafeMessage.Function() == ESCPSDataReceivedNotificationRequest)
+ {
+ TLegacyDataMonitoringNotificationRequest& dmmsg = static_cast<TLegacyDataMonitoringNotificationRequest&>(msg);
+
+ if (act->iSafeMessage.Int0() == aMessage.Int0()
+ && dmmsg.iDirection == aDirection)
+ {
+ ASSERT(iConnection.UniqueId() == dmmsg.iClientId);
+ act->SetCancelRequest(aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(act->iSafeMessage.Function(), TEBase::TCancel().CRef());
+ iConnection.DontCompleteCurrentRequest();
+ cancelled = ETrue;
+ }
+ }
+ }
+ }
+ if (!cancelled)
+ {
+ if (aMessage.Int0() == KNifEMCompatibilityLayerEntireSubConnectionUid && !iConnection.ServiceProvider())
+ {
+ iConnection.SetReturn(KErrNotReady);
+ }
+ else if (aMessage.Int0() == KNifEMCompatibilityLayerFakeSubConnectionId && !iConnection.DefaultSubConnectionServiceProvider())
+ {
+ iConnection.SetReturn(KErrNotReady);
+ }
+ else
+ {
+ LOG(ESockLog::Printf(KESockConnectionTag,
+ _L8("CConnectionLegacy(%08x)::DataMonitoringNotificationCancel - direction %d - client return set to %d. Bad subconnection id. (%d) specified."),
+ this, aDirection, KErrArgument, aMessage.Int0()));
+
+ iConnection.SetReturn(KErrArgument);
+ }
+ }
+ }
+
+void AConnectionLegacy::IsSubConnectionActiveRequestL(const Den::RSafeMessage& aMessage)
+ {
+ TInt subConnUniqueId = aMessage.Int0();
+
+ switch(subConnUniqueId)
+ {
+ case KNifEMCompatibilityLayerEntireSubConnectionUid:
+ if(!iConnection.ServiceProvider())
+ {
+ iConnection.SetReturn(KErrNotReady);
+ return;
+ }
+ break;
+ case KNifEMCompatibilityLayerFakeSubConnectionId:
+ if(!iConnection.DefaultSubConnectionServiceProvider())
+ {
+ iConnection.SetReturn(KErrNotReady);
+ return;
+ }
+ break;
+ default:
+ iConnection.SetReturn(KErrArgument);
+ return;
+ }
+
+ const RPointerArray<CNodeActivityBase>& activities = iConnection.Activities();
+ for (TInt i = 0; i < activities.Count(); i++)
+ {
+ if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler)
+ {
+ ConnActivities::CConnLegacyRMessage2Activity* act = static_cast<ConnActivities::CConnLegacyRMessage2Activity*>(activities[i]);
+
+ if (act->iSafeMessage.Function() == ESCPSIsSubConnectionActiveRequest
+ && act->iSafeMessage.Int0() == aMessage.Int0())
+ {
+ iConnection.SetReturn(KErrInUse);
+ return;
+ }
+ }
+ }
+
+ TLegacySubConnectionActiveRequest msg(iConnection.UniqueId(), aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(aMessage.Function(), msg);
+ iConnection.DontCompleteCurrentRequest();
+ }
+
+void AConnectionLegacy::IsSubConnectionActiveCancel(const Den::RSafeMessage& aMessage)
+ {
+ const RPointerArray<CNodeActivityBase>& activities = iConnection.Activities();
+ TBool cancelled = EFalse;
+ for (TInt i = 0; i < activities.Count(); i++)
+ {
+ if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler)
+ {
+ ConnActivities::CConnLegacyRMessage2Activity* act = static_cast<ConnActivities::CConnLegacyRMessage2Activity*>(activities[i]);
+
+ if (act->iSafeMessage.Function() == ESCPSIsSubConnectionActiveRequest
+ && act->iSafeMessage.Int0() == aMessage.Int0())
+ {
+ act->SetCancelRequest(aMessage);
+ iConnection.CMMSockSubSession::ReceivedL(act->iSafeMessage.Function(), TEBase::TCancel().CRef());
+ iConnection.DontCompleteCurrentRequest();
+ cancelled = ETrue;
+ }
+ }
+ }
+ if (!cancelled)
+ {
+ iConnection.SetReturn(KErrArgument);
+ }
+ }
+
+TBool AConnectionLegacy::DoesConnectionInfoExist(const TDesC8& aInfoBuf, const TConnectionClientInfo& aInfo)
+ {
+ TConnectionClientInfo info;
+ TPckg<TConnectionClientInfo> des(info);
+ const TUint KEntrySize = sizeof(TConnectionClientInfo);
+ const TUint8* ptr = aInfoBuf.Ptr();
+ const TUint8* end = ptr + aInfoBuf.Length();
+ while(ptr < end)
+ {
+ __ASSERT_DEBUG((end - ptr) >= KEntrySize, User::Panic(KSpecAssert_ESockSSockscnLgc, 8)); // array size is multiple of element size
+ des.Copy(ptr, KEntrySize);
+ if(info.iProcessId == aInfo.iProcessId && info.iUid == aInfo.iUid && info.iThreadId == aInfo.iThreadId)
+ {
+ return ETrue;
+ }
+ ptr += KEntrySize;
+ }
+ return EFalse;
+ }
+