diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/ssock/SS_SES.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/ssock/SS_SES.CPP Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1294 @@ +// Copyright (c) 1997-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: +// + +#include +#include +#include +#include "ss_msgs.h" +#include +#include +#include +#include "ss_subconn.h" +#include +#include "SS_rslv.H" +#include "SS_conn.H" +#include "ss_connectionsession.h" +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + +#include "ss_apiext_messages.h" +#include + +#include + +#include +#ifdef SYMBIAN_ZERO_COPY_NETWORKING +#include +#include +#else +#include +#endif // SYMBIAN_ZERO_COPY_NETWORKING +#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_ESockSSockS_SES, "ESockSSockS_SES."); +#endif + +#define MSG_PRM(prmIndex) (prmIndex) + +using namespace NetInterfaces; +using namespace ESock; +//using namespace Elements; +using namespace Messages; +using namespace Den; +using namespace CommsFW; + +class RNullableMessage : public RMessage2 + { +public: + void NullHandle() const + { + // Although this casting away of const looks awful it's in keeping with the ability to Complete() const + // messages - perhaps iHandle should have been mutable? + const_cast(*this).iHandle = 0; + } + }; + +/** +Constructor +*/ +CSockSession::CSockSession(TUidType aUid, TSessionUniqueId aSessionUniqueId) +: CWorkerSession(aUid, aSessionUniqueId) + { + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSession(%08x):\tConstructor"), this) ); + SocketServer::NewSession(); + } + +/*static*/ CSockSession* CSockSession::NewL(TProcessId aProcessId, TUidType aUid, TSessionUniqueId aSessionUniqueId) + { + + CSockSession* self = new (ELeave) CSockSession(aUid, aSessionUniqueId); + CleanupStack::PushL(self); + self->ConstructL(aProcessId); + CleanupStack::Pop(self); + return self; + } + +void CSockSession::ConstructL(TProcessId aProcessId) + { +#ifdef SYMBIAN_TRACE_ENABLE + // Document the owner of the session + TLogTextBuf buf; + buf.Format(_L8("CSockSession %08x:\tConstructL()"), this); + RProcess cliProc; + if (cliProc.Open(aProcessId) == KErrNone) + { + TName cliName = cliProc.Name(); + TInt index = cliName.LocateReverse('['); + if (index >= 1) + { + cliName.SetLength(index); + } + TUint processId = cliProc.Id(); + iProcessName.Copy(cliName); + buf.AppendFormatIgnoreOverflow(_L8(" pid=%x \"%S\""), processId, &iProcessName); + // Remove the "...[nnn]nnn" clutter from the name stored in the session + // (unless the name happens to begin with "["). + cliProc.Close(); + } + LOG(ESockLog::Printf(KESockServerTag, buf) ); +#endif + CWorkerSession::ConstructL(aProcessId); + } + +/** +Destroy +*/ +CSockSession::~CSockSession() + { + LOG( ESockLog::Printf(KESockServerTag, _L8("~CSockSession(%08x):\t\"%S\""), this, &iProcessName) ); + + if(iOptimalDealer) + { + iOptimalDealer->RemoveEligiblePid(iProcess.Id()); + } + + SocketServer::SessionClosing(); + } + +CSockManData* CSockSession::SockManGlobals() const + { + return WorkerThread().SockManGlobals(); + } + +TInt CSockSession::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic) +/** +Check the security policy of a process. +Called from a socket or resolver provider to check whether the process conforms to the security policy passed as +argument. +@see MProvdSecurityChecker +*/ + { + return aPolicy.CheckPolicy(iProcess, aDiagnostic) ? KErrNone : KErrPermissionDenied; + } + + +/** + Handle messages for this server. In a few cases the messages will be dealt with accordingly, + but in most cases they will be 1) forwarded to seperate player or 2) be handled by ProcessMessageL + if the Player is co-resident in this thread. + @param aMessage Standard IPC request from client side +*/ +void CSockSession::ServiceL(const RMessage2& aMessage) + { + LOG( + TBuf8<64> messName; + ESockLog::IPCMessName((TSockMess) aMessage.Function(), messName); + ESockLog::Printf(KESockServerTag, _L8("CSockSession(%08x):\tServiceL, Message(%08x) [%S] \"%S\" int3=%08x"), + this, aMessage.Handle(), &messName, &iProcessName, SubSessionFromHandle(aMessage.Int3(), TCFSubSessInfo(TCFSubSessInfo::EAny))); + ); + + const CWorkerThread& owner=WorkerThread(); + const CPitBoss& pitBoss = owner.PitBoss(); + + if(pitBoss.TestImmediateShutdownPresent()) + { + User::Leave(KErrServerTerminated); + } + + iComplete=ETrue; // Whether to complete RMessage2 immediately + iReturn=KErrNone; // Default return value if completing RMessage2 here + iOurMessage = &aMessage; + + CWorkerSubSession* ss = NULL; + + TWorkerId worker=TWorkerThreadPublicInfo::ENullWorkerId; + const TInt function = aMessage.Function(); + +#if defined(_DEBUG_SOCKET_FUNCTIONS) + if(function != ESSDbgControl && iDebugParking.iNumOutstanding > 0) + { + // Weakness here; if it's a session request then the 4th arg may be random stack junk. Major mitigation is that almost certainly they're in UDEB which gives near-certainty + // of it being the stack fill pattern (eg 0xCCCCCCCC) so a collision is very unlikely to be seen (and only in the few cases where debug parking is employed). To improve this + // need to test whether it's a sub-session operation; reorganising the IPC list will help this + if(iDebugParking.iSubSessHandle == 0 || iDebugParking.iSubSessHandle == aMessage.Int3()) + { + User::LeaveIfError(Dealer()->ParkRequest(this, aMessage, CCommonDealer::EDebugParking)); + --iDebugParking.iNumOutstanding; + DontCompleteCurrentRequest(); + return; + } + } +#endif + switch(function) + { + /* Cases handled without a player */ + case ESSRequestOptimalDealer: + RequestOptimalDealerL(); + break; + + case ESSInstallExtension: + LOG(ESockLog::Printf(_L8("WARNING: unsupported function ESSInstallExtension called, CSockSession(%08x)"), this)); + SetReturn(KErrNotSupported); + break; + + case ESSExclusiveMode: + LOG(ESockLog::Printf(_L8("WARNING: unsupported function ESSExclusiveMode called, CSockSession(%08x)"), this)); + SetReturn(KErrNone); + break; + + case ESSClearExclusiveMode: + LOG(ESockLog::Printf(_L8("WARNING: unsupported function ESSClearExclusiveMode called, CSockSession(%08x)"), this)); + SetReturn(KErrNone); + break; + + case ESSNumProtocols: + NumProtocolsL(); + break; + + case ESSProtocolInfo: + ProtocolInfoL(); + break; + + case ESSProtocolInfoByName: + ProtocolInfoByNameL(); + break; + + /* Cases for a Player to deal with, protocol level */ + case ESSProtocolStart: + case ESSProtocolStop: + case ESoCreate: + case ESRCreate: + if(pitBoss.GetWorkerForProtocol(aMessage.Int0(),aMessage.Int1(),aMessage.Int2(), worker)) + { + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), worker); + } + else + { + ParkIfIndeterminateRequest(aMessage, KErrBadName); + } + break; + + case ESoCreateWithConnection: + { + TPckgBuf argPkg; + SafeMessage().ReadL(MSG_PRM(0),argPkg); + ss = CConnectionFromHandle(argPkg().iHandle); + if(!ss) + { + PanicClient(ESockBadHandle); + } + else + { + // Forward the message to the connection's (control) thread. It's best placed to decide which of its data threads it really belongs in + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), ss->Player().WorkerId()); + } + } + break; + case ESoCreateWithSubConnection: + { + TPckgBuf argPkg; + SafeMessage().ReadL(MSG_PRM(0),argPkg); + ss = CSubConnectionFromHandle(argPkg().iHandle); + if (!ss) + { + PanicClient(ESockBadHandle); + } + else + { + // Forward the message to the subconnection's (control) thread. It's best placed to decide which of its data threads it really belongs in + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), ss->Player().WorkerId()); + } + break; + } + case EHRCreateWithConnection: + case EHRCreate: + case ENDCreate: + if(pitBoss.GetWorkerForProtocol(aMessage.Int0(), KUndefinedSockType, aMessage.Int1(), worker)) + { + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), worker); + } + else + { + ParkIfIndeterminateRequest(aMessage, KErrBadName); + } + break; + + case ESoCreateNull: + // Attempt to pass to co-resident player + if(owner.Player()) + { + worker = WorkerId(); + } + else + { // No co-resident player, pass to NullSocket handling player known to PitBoss + VERIFY(pitBoss.GetWorkerForNullSocket(worker)); + } + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), worker); + break; + + case ECNCreate: + ForwardTierRequestL(aMessage); + break; + + // Connection Messages + case ECNCreateWithName: + { + // The cloned connection must be created on the same [control] Player that owns the original + TName name; + aMessage.ReadL(0, name); + User::LeaveIfError(CSockSubSession::FetchSubSessionFromName(name, TCFSubSessInfo(TCFSubSessInfo::EConnection), owner, ss)); + ForwardMessageL(aMessage, *ss); // can't be indeterminate request; already created the clone source + break; + } + + /* All else (cases for a Player to deal with, subsession level) */ + +// socket messages + + case ESoClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::ESocket)); + break; + + case ESoConnect: + case ESoShutdown: + case ESoSendToNoLength: + case ESoSendNoLength: + case ESoSendTo: + case ESoSend: + case ESoWrite: + case ESoRecvFromNoLength: + case ESoRecvNoLength: + case ESoRecvOneOrMore: + case ESoRecvFrom: + case ESoRecv: + case ESoRead: + case ESoBind: + case ESoAccept: + case ESoListen: + case ESoSetOpt: + case ESoGetOpt: + case ESoIoctl: + case ESoGetDiscData: + case ESoGetLocalName: + case ESoGetRemoteName: + case ESoReference: + ss=CSocketFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + case ESoCancelRecv: + case ESoCancelSend: + case ESoCancelIoctl: + case ESoCancelConnect: + case ESoCancelAccept: + case ESoCancelAll: + ss=CSocketFromHandle(aMessage.Int3()); + if(ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + LOG(ESockLog::Printf(_L8("CSockSession::ServiceL: BAD ESoCancelAll"))); + } + break; + + case ESoSocketInfo: + ss=CSocketFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + SetReturn(KErrBadHandle); + } + break; + + case ESoTransfer: + TransferSocketL(); + break; + +// Host resolver message types + + case EHRClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::EHostResolver)); + break; + + case EHRCancel: + ss=CHostResolverFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + LOG( ESockLog::Printf(_L8("CSockSession::ServiceL: BAD EHRCancel")) ); + } + break; + + case EHRGetByName: + case EHRNext: + case EHRGetByAddress: + case EHRGetHostName: + case EHRSetHostName: + case EHrQuery: + case EHrQueryNext: + case EHRSetOpt: + ss=CHostResolverFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + +// Service resolver message types + + case ESRClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::EServiceResolver)); + break; + + case ESRGetByName: + case ESRGetByNumber: + case ESRRegisterService: + case ESRRemoveService: + ss=CServiceResolverFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + case ESRCancel: + ss=CServiceResolverFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + LOG( ESockLog::Printf(_L8("CSockSession::ServiceL: BAD ESRCancel")) ); + } + break; + +// Net database message types + + case ENDClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::ENetDatabase)); + break; + + case ENDQuery: + case ENDAdd: + case ENDRemove: + ss=CNetDatabaseFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + case ENDCancel: + ss=CNetDatabaseFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + LOG( ESockLog::Printf(_L8("CSockSession::ServiceL: BAD ENDCancel")) ); + } + break; + case ECNClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::EConnection)); + break; + case ECNStart: + case ECNSetStartPrefs: + case ECNStop: + case ECNReference: + case ECNProgress: + case ECNProgressNotification: + case ECNCancelProgressNotification: + case ECNLastProgressError: + case ECNServiceChangeNotification: + case ECNCancelServiceChangeNotification: + case ECNGetIntSetting: + case ECNGetBoolSetting: + case ECNGetDes8Setting: + case ECNGetDes16Setting: + case ECNGetLongDesSetting: + case ECNEnumerateConnections: + case ECNGetConnectionInfo: + case ECNIoctl: + case ECNCancelIoctl: + case ECNControl: + case ECNAttach: + case ECNAllInterfaceNotification: + case ECNCancelAllInterfaceNotification: + case ECNCancelAllSubConnectionNotification: + case ECNEnumerateSubConnections: + case ECNAllSubConnectionNotification: + case ECNWaitForIncoming: + case ECNCancelWaitForIncoming: + + case ESCPSStop: + case ESCPSProgressNotification: + case ESCPSCancelProgressNotification: + case ESCPSDataTransferred: + case ESCPSDataTransferredCancel: + case ESCPSDataSentNotificationRequest: + case ESCPSDataSentNotificationCancel: + case ESCPSDataReceivedNotificationRequest: + case ESCPSDataReceivedNotificationCancel: + case ESCPSIsSubConnectionActiveRequest: + case ESCPSIsSubConnectionActiveCancel: + + case ESCPSGetSubConnectionInfo: + ss=CConnectionFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + + case ESCCreate: + { + TPckgBuf argPkg; + SafeMessage().ReadL(MSG_PRM(0),argPkg); + ss=CConnectionFromHandle(argPkg().iHandle); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + } + case ESCClose: + CloseSubSessionL(aMessage, TCFSubSessInfo(TCFSubSessInfo::ESubConnection)); + break; + + case ESCAddSocket: + case ESCRemoveSocket: + case ESCSetParameters: + case ESCGetParameters: + case ESCGetParametersLength: + case ESCEventNotificationSetup: + case ESCEventNotification: + case ESCEventAllNotifications: + case ESCEventNotificationCancel: + case ESCControl: + case ESCStart: + case ESCStop: + ss=CSubConnectionFromHandle(aMessage.Int3()); + if (ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + +// Server debug messages +#if defined (_DEBUG_SOCKET_FUNCTIONS) + case ESSDbgMarkHeap: + case ESSDbgCheckHeap: + case ESSDbgMarkEnd: + case ESSDbgFailNext: + case ESSDbgFailNextMbuf: + case ESSDbgSetMbufPoolLimit: + case ESSDbgCheckMbuf: + case ESSDbgMbufFreeSpace: + case ESSDbgMbufTotalSpace: + case ESSDbgCheckFailNext: + { + if(!pitBoss.ModuleConfigurationComplete()) + { + if (Dealer()->ParkRequest(this, aMessage, CCommonDealer::EIndeterminateDuringBoot) != KErrNone) + { + //Something terrible has just happened. + //We could not park the request. + //Since this is a debug call it is probably a good idea to panic here, + //hopefully providing a chance to see what is going wrong. + __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ESockSSockS_SES, 1)); + } + else + { + DontCompleteCurrentRequest(); + } + } + else + { + SSDbgFunctionL(aMessage); + } + break; + } +#endif // _DEBUG_SOCKET_FUNCTIONS + + default: + ss = SubSessionFromHandle(aMessage.Int3(), TCFSubSessInfo(TCFSubSessInfo::EAny)); + + if(ss) + { + ForwardMessageL(aMessage, *ss); + } + else + { + PanicClient(ESockBadHandle); + } + break; + } + + // Message handlers can change the state of the iMessage if they want to hold onto the message. + // They can also write a return value to iReturn. + if (iComplete) + { + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSession(%08x):\tServiceL, Complete message(%08x) with %d."), this, aMessage.Handle(), iReturn) ); + aMessage.Complete(iReturn); + } + } + +#if defined (_DEBUG_SOCKET_FUNCTIONS) +void CSockSession::DispatchDebugMessageL(const RMessage2& aMessage) + { + Elements::RResponseMsg responseMsg(aMessage, aMessage.Int0(), 1, 2); + + // Construct our message in place + TBuf8 msgDst; + ESockDebug::TControlMsg* msg = static_cast(responseMsg.ReadClientReqMsg(msgDst)); + __ASSERT_ALWAYS(msg, Fault(EDebugSupport)); + + // Self dispatch our message and return any error code + TPckgBuf returnValue; + TInt& debugStatus = returnValue(); + debugStatus = msg->DispatchL(this); + SafeMessage(aMessage).WriteL(MSG_PRM(0), returnValue); + } + + +#endif // _DEBUG_SOCKET_FUNCTIONS + +#if defined (_DEBUG_SOCKET_FUNCTIONS) +void CSockSession::SSDbgFunctionL(const RMessage2& aMessage) + { + switch(aMessage.Function()) + { + case ESSDbgMarkHeap: + __UHEAP_MARK; + break; + case ESSDbgCheckHeap: + __UHEAP_CHECK(aMessage.Int0()); + break; + case ESSDbgMarkEnd: + __UHEAP_MARKENDC(aMessage.Int0()); + break; + case ESSDbgFailNext: + { + const CWorkerThread& owner=WorkerThread(); + CPitBoss& pitBoss = owner.PitBoss(); + + // We set the fail point for all heaps, rather than just the current Dealer. This could lead to a failure not related + // directly to whatever the client test code is trying to exercise but it all helps find bugs + pitBoss.SetFailNextForAllHeaps(aMessage.Int0()); + break; + } + case ESSDbgCheckFailNext: + { + // Report whether any heap has ended "FailNext" mode set by ESSDbgFailNext, which generally indicates that some code + // under test hasn't explored all allocation points + const CWorkerThread& owner=WorkerThread(); + CPitBoss& pitBoss = owner.PitBoss(); + SetReturn(pitBoss.TestFailNextForAllHeaps()); + break; + } + // MBuf specific allocation fails and checks. + case ESSDbgFailNextMbuf: + { +#ifdef SYMBIAN_ZERO_COPY_NETWORKING + RCommsBufPond pond=TCommsBufPondTLSOp::Get(); + if (pond.IsNull()) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TCommsBufPondDbg pondDbg(pond); + pondDbg.__DbgSetFailAfter(aMessage.Int0()); + } +#else + CMBufManager* mbufMan=CMBufManager::Context(); + if (mbufMan==NULL) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + mbufMan->__DbgSetFailAfter(aMessage.Int0()); + } +#endif // SYMBIAN_ZERO_COPY_NETWORKING + break; + } + case ESSDbgSetMbufPoolLimit: + { +#ifdef SYMBIAN_ZERO_COPY_NETWORKING + RCommsBufPond pond=TCommsBufPondTLSOp::Get(); + if (pond.IsNull()) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TCommsBufPondDbg pondDbg(pond); + pondDbg.__DbgSetPoolLimit(aMessage.Int0()); + } +#else + CMBufManager* mbufMan=CMBufManager::Context(); + if (mbufMan==NULL) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + mbufMan->__DbgSetPoolLimit(aMessage.Int0()); + } + +#endif // SYMBIAN_ZERO_COPY_NETWORKING + break; + } + case ESSDbgCheckMbuf: + { +#ifdef SYMBIAN_ZERO_COPY_NETWORKING + RCommsBufPond pond=TCommsBufPondTLSOp::Get(); + if (pond.IsNull()) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TCommsBufPondDbg pondDbg(pond); + if (pondDbg.__DbgGetBufTotal()-pondDbg.__DbgGetBufSpace()!=aMessage.Int0()) + { + Fault(EBadMbufCheck); + } + } +#else + CMBufManager* mbufMan=CMBufManager::Context(); + if (mbufMan==NULL) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + if (mbufMan->__DbgGetBufTotal()-mbufMan->__DbgGetBufSpace()!=aMessage.Int0()) + Fault(EBadMbufCheck); + } +#endif + break; + } + case ESSDbgMbufFreeSpace: + { +#ifdef SYMBIAN_ZERO_COPY_NETWORKING + RCommsBufPond pond=TCommsBufPondTLSOp::Get(); + if (pond.IsNull()) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TPckgBuf c; + TInt& space=c(); + TCommsBufPondDbg pondDbg(pond); + space=pondDbg.__DbgGetBufSpace(); + SafeMessage().WriteL(MSG_PRM(0),c); + } +#else + CMBufManager* mbufMan=CMBufManager::Context(); + if (mbufMan==NULL) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TPckgBuf c; + TInt& space=c(); + space=mbufMan->__DbgGetBufSpace(); + SafeMessage().WriteL(MSG_PRM(0),c); + } +#endif + break; + } + case ESSDbgMbufTotalSpace: + { +#ifdef SYMBIAN_ZERO_COPY_NETWORKING + RCommsBufPond pond=TCommsBufPondTLSOp::Get(); + if (pond.IsNull()) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TPckgBuf c; + TInt& size=c(); + TCommsBufPondDbg pondDbg(pond); + size=pondDbg.__DbgGetBufTotal(); + SafeMessage().WriteL(MSG_PRM(0),c); + } +#else + CMBufManager* mbufMan=CMBufManager::Context(); + if (mbufMan==NULL) + { + PanicClient(EMbufManagerNotLoaded); + } + else + { + TPckgBuf c; + TInt& size=c(); + size=mbufMan->__DbgGetBufTotal(); + SafeMessage().WriteL(MSG_PRM(0),c); + } +#endif // SYMBIAN_ZERO_COPY_NETWORKING + } + break; + + // Bad message + default: + PanicClient(ESockBadHandle); + } + } +#endif +// _DEBUG_SOCKET_FUNCTIONS + + + +/** +Return a CSocket given a client's handle +*/ +CSocket* CSockSession::CSocketFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::ESocket))); + } + +/** +Return a Flow and SCPR CommsIds given a socket's handle +*/ +TBool CSockSession::FlowAndSCPRFromSocketHandle(TUint aHandle, Messages::TNodeId& aFlow, Messages::TNodeId& aSCPR) + { + SubSessions().Lock(); + + TInt found = EFalse; + + CSocket* sock = static_cast(iSubSessions.At(aHandle, TCFSubSessInfo(TCFSubSessInfo::ESocket))); + if (sock) + { + found = sock->GetFlowAndSCPR(aFlow, aSCPR); + } + + SubSessions().Unlock(); + + return found; + } + +/** +Find a CNameResolver from a clients handle +*/ +CHostResolver* CSockSession::CHostResolverFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::EHostResolver))); + } + +/** +Find a CServiceresolver from a clients handle +*/ +CServiceResolver* CSockSession::CServiceResolverFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::EServiceResolver))); + } + +/** +Find a CNetDatabase from a handle +*/ +CNetDatabase* CSockSession::CNetDatabaseFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::ENetDatabase))); + } + +/** +Find a CConnection from a handle +*/ +ESock::CConnection* CSockSession::CConnectionFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::EConnection))); + } + +/** +find a CSubConnection from a handle + +*/ +CSubConnection* CSockSession::CSubConnectionFromHandle(TUint aHandle) + { + return static_cast(SubSessionFromHandle(aHandle, TCFSubSessInfo(TCFSubSessInfo::ESubConnection))); + } + +void CSockSession::CloseSubSessionL(const RMessage2& aMessage, TSubSessInfo aType) + { + CWorkerSubSession* subSess = NULL; + + { + SubSessions().Lock(); + + subSess = iSubSessions.At(aMessage.Int3(), aType); + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSession(%08x):\tCloseSubSession(%08x, %d) - subSess %08x"), this, aMessage.Int3(), aType.iType, subSess)); + if(subSess) + { + VERIFY_RESULT(iSubSessions.Remove(aMessage.Int3()), subSess); + } + + SubSessions().Unlock(); + } + + if(subSess) + { + ForwardMessageL(aMessage, *subSess); + } + else + { + SetReturn(KErrBadHandle); // Close() is always safe + } + } + + +/** +Search for an optimal dealer. If one is found set the iOptimalDealer member, register +the requesting PID on the optimal dealer and return the dealer server name to the client. +*/ +void CSockSession::RequestOptimalDealerL() + { + /* Wont accept this if we're shutting down or if we've + already requested optimal dealer (successfully) before */ + if(SocketServer::IsShuttingDown()) + { + User::Leave(KErrServerTerminated); + } + else if(iOptimalDealer) + { + PanicClient(EConnectingAlready); + } + else // Ok, find optimal dealer and register it with session, tell nice client... + { + TSessionPref pref; + TPckg package(pref); + SafeMessage().ReadL(MSG_PRM(0), package); + if(PitBoss().FindOptimalDealer(pref, iOptimalDealer)) + { + // Add PID to table of authorised clients. + iOptimalDealer->AddEligiblePidL(iProcess.Id()); + SafeMessage().WriteL(MSG_PRM(1), iOptimalDealer->ServerName()); + SetReturn(KErrNone); + LOG(ESockLog::Printf(KESockSessDetailTag, _L("CSockSession(%08x):\tRequestOptimalDealerL %S for 0x%X"), this, &iOptimalDealer->ServerName(), static_cast(iEligiblePid)) ); + } + else + { + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSession(%08x):\tRequestOptimalDealerL KErrNotFound"), this) ); + iOptimalDealer=NULL; + // Optimal Dealer requests don't get parked during boot - there's a risk of creating a hard-to-debug startup deadlock + // which outweighs the performance benefit + SetReturn(KErrNotFound); + } + } + } + +/** +Determine the owning Player and forward the TransferSocket message to it. +*/ +void CSockSession::TransferSocketL() + { + TName name; + SafeMessage().ReadL(MSG_PRM(0), name); + CWorkerSubSession* socket; + TInt err = CSocket::FetchSubSessionFromName(name, TCFSubSessInfo(TCFSubSessInfo::ESocket), WorkerThread(), socket); + if(err == KErrNone) + { + ForwardMessageL(*iOurMessage, *socket); + } + User::Leave(KErrNotFound); // name bad or Player exited + } + +/** +Handle a request for the number of loaded protocols. +*/ +void CSockSession::NumProtocolsL(void) + { + if(!PitBoss().ModuleConfigurationComplete()) + { + ParkIfIndeterminateRequest(Message(), KErrNone); + } + else + { + TUint num=PitBoss().GetNumProtocols(); + TPtrC8 d((TUint8 *)&num,sizeof(num)); + if (SafeMessage().Write(MSG_PRM(0),d) != KErrNone) + { + DontCompleteCurrentRequest(); + } + } + } + +/** +Get info for a protocol by index. +*/ +void CSockSession::ProtocolInfoL(void) + { + TWorkerId worker; + if(!PitBoss().GetWorkerForProtocol(Message().Int1(), worker)) + { + ParkIfIndeterminateRequest(Message(), KErrNotFound); + } + else + { + ForwardMessageL(Message(), TPlayerForwardRequestMsg::UnusedParam(), worker); + } + } + +/** +Get protocol info by name. +*/ +void CSockSession::ProtocolInfoByNameL( ) + { + TProtocolName name; + SafeMessage().ReadL(MSG_PRM(1),name); + + TWorkerId worker; + if(!PitBoss().GetWorkerForProtocolByName(name, worker)) + { + ParkIfIndeterminateRequest(Message(), KErrNotFound); + } + else + { + ForwardMessageL(Message(), TPlayerForwardRequestMsg::UnusedParam(), worker); + } + } + +/** +Panic the client. +*/ +void CSockSession::PanicClient(TESockPanic aPanic) + { + SafeMessage().PanicClient(KESockClientPanic, (TInt) aPanic); + DontCompleteCurrentRequest(); + } + + +#ifdef SYMBIAN_NETWORKING_PERFMETRICS +void CSockSession::IncludePerformanceData(TInt aDeltaClientRxBytes, TInt aDeltaClientRxBuffBytes, TInt aDeltaClientTxBytes) + { + SockManGlobals()->IncludePerformanceData(aDeltaClientRxBytes, aDeltaClientRxBuffBytes, aDeltaClientTxBytes); + } +#endif + +/** +Constructor +*/ +CSockSubSession::CSockSubSession(CSockSession* aSession, CPlayer* aPlayer, const Den::TSubSessionUniqueId aSubSessionUniqueId) +: CWorkerSubSession(aSession, aPlayer, aSubSessionUniqueId) + { + } + +void CSockSubSession::ConstructL(CProtocolBase* aProtocol) + { + CWorkerSubSession::ConstructL(); + if(aProtocol) + { + CSockSessionProxy* sp = static_cast(SessionProxy()); + sp->AddProtocolL(aProtocol); + } + } + +CSockSession* CSockSubSession::Session() + { + return static_cast(Den::CWorkerSubSession::Session()); + } + +const CSockSession* CSockSubSession::Session() const + { + return static_cast(Den::CWorkerSubSession::Session()); + } + +void CSockSubSession::DeleteMe() + { + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSubSession %08x:\tDeleteMe() - iSubSessionUniqueId %08X, iType %d, iSession %08x"), this, iSubSessionUniqueId, Type().iType, iSession) ); + + switch(Type().iType) + { + case TCFSubSessInfo::ESocket: + static_cast(this)->InitiateDestruction(); + break; + case TCFSubSessInfo::EHostResolver: + static_cast(this)->InitiateDestruction(); + break; + case TCFSubSessInfo::EServiceResolver: + { + // Remove the subsession from the session's subsession list. + if(iSession) + { + iSession->SubSessions().Lock(); + + CSubSessionIx::TSubSessionHandle handle; + if(iSession->SubSessions().Find(this, handle) == KErrNone) + { + iSession->PitBoss().RemoveSubSession(handle, iSession); + } + + iSession->SubSessions().Unlock(); + } + + delete this; + } + break; + case TCFSubSessInfo::ENetDatabase: + { + // Remove the subsession from the session's subsession list. + if(iSession) + { + iSession->SubSessions().Lock(); + + CSubSessionIx::TSubSessionHandle handle; + if(iSession->SubSessions().Find(this, handle) == KErrNone) + { + iSession->PitBoss().RemoveSubSession(handle, iSession); + } + + iSession->SubSessions().Unlock(); + } + + delete this; + } + break; + case TCFSubSessInfo::EConnection: + //Mimic the client sending ECNClose (without RMessage2) + { + const TNodeId& c = static_cast(*this).Id(); + RClientInterface::OpenPostMessageClose(TNodeCtxId(ECNClose, c), TNodeCtxId(ECNClose, c), ESock::TCFInternalEsock::TSubSess(ECNClose,RMessage2()).CRef()); + } + break; + case TCFSubSessInfo::ESubConnection: + //Mimic the client sending ESCClose (without RMessage2) + { + const TNodeId& sc = static_cast(*this).Id(); + RClientInterface::OpenPostMessageClose(sc, TNodeCtxId(ESCClose, sc), ESock::TCFInternalEsock::TSubSess(ESCClose,RMessage2()).CRef()); + } + break; + default: + //Please support your new subsession type + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockS_SES, 2)); + } + + } + +CSockSubSession::~CSockSubSession() + { + LOG(ESockLog::Printf(KESockServerTag, _L8("CSockSubSession(%08x):\t~CSockSubSession Session(%08x)"), this, iSession) ); + + // A subsession has a session proxy unless OOM prevented it + if(SessionProxy()) + { + SessionProxy()->NotifySubSessionDestroyed(); + } + } + +//Default implementation - must be specialised if used +void CSockSubSession::CommsApiExtBindIfaceL(const RMessage2& /*aMessage*/) + { + User::Leave(KErrNotSupported); + } + +//Default implementation - must be specialised if used +void CSockSubSession::CommsApiExtIfaceSendReceiveL(const RMessage2& /*aMessage*/) + { + User::Leave(KErrNotSupported); + } + +//Default implementation - must be specialised if used +void CSockSubSession::CloseExtensionInterface(const RMessage2& /*aMessage*/) + { + } + +//Default implementation - must be specialised if used +void CSockSubSession::CancelAndCloseAllClientExtIfaces() + { + } + +/** Client request to forwarded to the thread of the tier manager for the given tier. Possibilities: +(1) Mapping of tier to worker thread already known; can forward directly +(2) Mapping unknown & mappings loaded; fail request +(3) Mapping unknown & mappings not yet loaded; park request and request tier resolver to load mappings +(4) Tier resolver not yet located (ie during boot); request parked as indeterminate + +Because only the main thread is guaranteed to have a binding to the tier resolver, the request for +mappings is always made by it, ie a secondary Dealer sends the request to load mappings to it. After +adding the mappings the main thread then messages all other workers to tell them to unpark any requests +awaiting the tier mappings. + +The last thing added is the dummy "tiers loaded" flag, which serves to indicate to Dealers that resolution +is complete. +*/ +void CSockSession::ForwardTierRequestL(const RMessage2& aMessage) + { + TWorkerId worker; + TUint family = aMessage.Int0(); + TUint protocol = aMessage.Int2(); + TUid tierUid = TierManagerUtils::MapTierIdsL(TUid::Uid(family), protocol); + CPitBoss& pitBoss = PitBoss(); + if(pitBoss.GetWorkerForTier(tierUid.iUid, worker)) + { + //ForwardMessageL(aMessage, reinterpret_cast(tierUid.iUid), worker); + ForwardMessageL(aMessage, TPlayerForwardRequestMsg::NormalCreationFlag(), worker); + } + else + { + // No mapping found; either it's a bad id or we've yet to load mappings + TInt err = KErrNone; + if(PitBoss().TierMappingsLoaded()) + { + err = KErrBadName; + } + else + { + err = Dealer()->ParkRequest(this, aMessage, CCommonDealer::EAwaitingTierToWorkerMapping); + } + if(err == KErrNone) + { + if(WorkerId() != TWorkerThreadPublicInfo::EMainThread) + { + TWorkerLoadTierMappings msg; + WorkerThread().PostMessage(TWorkerThreadPublicInfo::EMainThread, msg); + } + else + { + PitBoss().RequestLoadTierMapping(); + } + } + if(err == KErrNone) + { + DontCompleteCurrentRequest(); + } + else + { + SetReturn(err); + } + } + } + +CWorkerThread& CSockSession::WorkerThread() const + { + return static_cast(CWorkerSession::WorkerThread()); + } + + +CPitBoss& CSockSession::PitBoss() const + { + return static_cast(CWorkerSession::PitBoss()); + } + +void CSockSession::Disconnect(const RMessage2& aMessage) + { + LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSession(%08x):\tDisconnect \"%S\""), this, &iProcessName) ); + CWorkerSession::Disconnect(aMessage); + }