--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/SS_MAN.CPP Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,1411 @@
+// 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 <comms-infras/ss_roles.h>
+#include <ss_glob.h>
+//#include <es_ini.h>
+#include <comms-infras/ss_log.h>
+#include <ss_protprov.h>
+#include <comms-infras/ss_sapshim.h>
+#include <ss_sock.h>
+#include "SS_rslv.H"
+#include "SS_conn.H"
+#include "ss_eintsockimpl.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_ESockSSockS_MAN, "ESockSSockS_MAN.");
+#endif
+
+using namespace ESock;
+
+#if defined (_DEBUG)
+
+/** @file
+Check that the protocol has filled in the protocol structure
+As much as we can anyway.
+Note that this function needs to be maintained in parallel with the contents of es_sock.h and es_prot.h
+
+A panic in this function means that the protocol has returned an invalid TServerProtocolDesc
+
+@internalComponent
+*/
+void CheckProtocolList(TServerProtocolDesc* aProtocolList,TInt aCount)
+ {
+ for (TInt i=0;i<aCount;i++)
+ {
+ if ((aProtocolList+i)->iServiceTypeInfo&0xFFFFFF00)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iNumSockets==(TInt)0xa5a5a5a5)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iName.Length()==0)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iAddrFamily==0 || (aProtocolList+i)->iAddrFamily==0xa5a5a5a5)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iSockType==0xa5a5a5a5)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ //If the socket has no support for sockets (NumSockets is 0)
+ //then it should be of SockType 0.
+ if ((aProtocolList+i)->iSockType==0)
+ {
+ if ((aProtocolList+i)->iNumSockets!=0)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ }
+ if ((aProtocolList+i)->iProtocol==0 || (aProtocolList+i)->iProtocol==0xa5a5a5a5)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((((aProtocolList+i)->iVersion.iMajor==0)&&((aProtocolList+i)->iVersion.iMinor==0)&&((aProtocolList+i)->iVersion.iBuild==0)))
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if (((aProtocolList+i)->iByteOrder!=EBigEndian && (aProtocolList+i)->iByteOrder!=ELittleEndian && (aProtocolList+i)->iByteOrder!=EOtherByteOrder))
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iServiceInfo&0xfffc0000)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iNamingServices&0xfffffe00)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if ((aProtocolList+i)->iSecurity&0xfffffffe)
+ {
+ Panic(EBadProtocolDescription);
+ }
+ if (((aProtocolList+i)->iMessageSize<0 && (aProtocolList+i)->iMessageSize!=KSocketMessageSizeNoLimit))
+ {
+ Panic(EBadProtocolDescription);
+ }
+ }
+ }
+#endif
+
+//
+// Protocol manager assumes that there will be an ini file setion called
+// [protocols] which will contain a single entry: protocols= the data for
+// which is a comma seperated list of further section names.
+// Each of these section names should contina a file name of a .PRT
+// and index number of the protocol inside this family and an optional
+// bindto= entry specifying which lower protocols this should be bound to.
+//
+// The protocol manager late loads (and binds) all protocols - keeping only CProtocolRef etc.
+// classes which contain enough data to reload the protocol when the first socket is
+// created. Protocols will the stay loaded unti lthe last client (who made a socket of
+// the specified type) closes. I.e. protocols are created for sockets but referenced by
+// sessions.
+//
+
+/**
+@internalComponent
+*/
+
+_LIT(KSockManMainSectionName,"sockman");
+_LIT(KProtocolListItemName,"protocols");
+_LIT(KFilenameItemName,"filename");
+_LIT(KIndexTagName,"index");
+_LIT(KBindToItemName,"bindto");
+_LIT(KBindFromItemName,"bindfrom");
+_LIT(KFlowFactoryUid, "flow_factory_uid");
+_LIT(KFlowProtocol, "flow_protocol_id");
+_LIT(KOpenAngle, "<");
+_LIT(KCloseAngle, ">");
+_LIT(KComma, ",");
+
+const TInt KDependSize = 32;
+
+
+void ProtocolManager::AddDependencyL(const TDesC& aDependentsList, const TDesC& aModuleToLoad)
+/**
+Adds a module to the dependency list. Dependency list is of form <a>b,c<d>e,f
+meaning that module "a" is dependant on "b" and "c" and requires module b and c to be loaded.
+
+@param aDependentsList list of dependant components to be loaded
+@param aModuleToLoad The module for which the dependency is added
+*/
+ {
+ CSockManData *globals=SockManGlobals::Get();
+
+ if (globals->iDeps == NULL)
+ {
+ globals->iDeps = HBufC::NewL(KDependSize);
+ }
+
+ TLex lex(aDependentsList);
+ TChar ch=0;
+ do
+ {
+ lex.Mark();
+
+ do
+ {
+ ch=lex.Get();
+ }
+ while (ch!=',' && ch!=0);
+
+ if (ch==',')
+ {
+ lex.UnGet();
+ }
+
+ TPtrC dependent=lex.MarkedToken();
+ lex.Get();
+
+ TBuf<50> searchBuf;
+ searchBuf.Append(KOpenAngle);
+ searchBuf.Append(dependent);
+ searchBuf.Append(KCloseAngle);
+
+ TPtr list = globals->iDeps->Des();
+ TInt reqLength = list.Length() + searchBuf.Length() + aModuleToLoad.Length();
+ if (reqLength >= list.MaxLength())
+ {
+ globals->iDeps = globals->iDeps->ReAllocL(reqLength);
+ list.Set(globals->iDeps->Des());
+ }
+
+ TInt pos = list.Find(searchBuf);
+ if (pos == KErrNotFound)
+ {
+ list.Append(searchBuf);
+ list.Append(aModuleToLoad);
+ }
+ else
+ {
+ pos++;
+ TInt endPos = list.Mid(pos).Find(KOpenAngle);
+ if (endPos != KErrNotFound)
+ {
+ endPos += pos;
+ list.Insert(endPos, KComma);
+ list.Insert(endPos + 1, aModuleToLoad);
+ }
+ else
+ {
+ list.Append(KComma);
+ list.Append(aModuleToLoad);
+ }
+ }
+ } while (ch != 0);
+ }
+
+TBool ProtocolManager::GetDependency(const TDesC& aTag,TPtrC &aList)
+/**
+Goes through the dependency list and gets the dependant modules for aTag
+
+@param aTag The protocol tag based on which the dependancy list is searched
+@param aList A list of components dependant on aTag protocol which are returned
+@return ETrue if a dependency for the component aTag is found else EFalse
+*/
+ {
+ CSockManData *globals=SockManGlobals::Get();
+
+ if(globals->iDeps)
+ {
+
+ TPtrC list = *globals->iDeps;
+
+ TBuf<50> tag(KOpenAngle);
+ tag.Append(aTag);
+ tag.Append(KCloseAngle);
+
+ TInt offset= list.Find(tag);
+
+ if(offset!=KErrNotFound)
+ {
+ aList.Set(list.Mid(offset+tag.Length()));
+ offset= aList.Find(KOpenAngle);
+ if(offset!=KErrNotFound)
+ {
+ aList.Set(aList.Mid(0,offset));
+ }
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+void ProtocolManager::InitL()
+/**
+Init data structures and hunt for protocols.
+*/
+ {
+ LOG( ESockLog::Printf(_L("ProtocolManager: Initialising.")) );
+
+ // Allocate global storage to be held in tls.
+ CSockManData *globals=SockManGlobals::Get();
+
+ globals->iProtocols=new(ELeave) TSglQue<CProtocolRef>(_FOFF(CProtocolRef,iLink));
+ CleanupStack::PushL(globals->iProtocols);
+ globals->iProtocolFamilies=new(ELeave) TSglQue<CProtocolFamilyRef>(_FOFF(CProtocolFamilyRef,iLink));
+ CleanupStack::Pop(globals->iProtocols);
+ }
+
+void ProtocolManager::ShutDown()
+/**
+free data structures
+*/
+ {
+ CSockManData* globals=SockManGlobals::Get();
+
+ TSglQueIter<CProtocolRef> i(*globals->iProtocols);
+ CProtocolRef* p=NULL;
+ while(p=i++,p!=NULL)
+ {
+ globals->iProtocols->Remove(*p);
+ delete p;
+ }
+
+ TSglQueIter<CProtocolFamilyRef> j(*globals->iProtocolFamilies);
+ CProtocolFamilyRef* f=NULL;
+ while(f=j++,f!=NULL)
+ {
+ globals->iProtocolFamilies->Remove(*f);
+ delete f;
+ }
+
+ // delete all the containers and lists of protocols etc.
+ delete globals->iProtocols;
+ delete globals->iProtocolFamilies;
+ delete globals->iDeps;
+
+ }
+
+void ProtocolManager::ProcessIniDataL()
+ {
+ LOG( ESockLog::Printf(_L("ProtocolManager: Retrieve ESock inidata.")) );
+
+ CSockManData *globals=SockManGlobals::Get();
+ const CESockIniData* ini=globals->IniData();
+
+ TPtrC protocols;
+ if (ini->FindVar(KSockManMainSectionName,KProtocolListItemName,protocols)==EFalse)
+ User::Leave(KErrBadName);
+
+ LOG( ESockLog::Printf(_L("ProtocolManager: Protocol list is %S"), &protocols) );
+ LOG( ESockLog::Printf(_L("ProtocolManager: Loading PRTs and setting up protocols.")) );
+
+ TLex lex(protocols);
+ TChar ch=0;
+ do
+ {
+ lex.Mark();
+
+ do
+ {
+ ch=lex.Get();
+ }
+ while (ch!=',' && ch!=0);
+
+ if (ch==',')
+ {
+ lex.UnGet();
+ }
+ TPtrC protTag=lex.MarkedToken();
+ lex.Get();
+ TPtrC fileName(NULL,0);
+
+ // If there is no filename present (legacy PRT based protocols) then we expect instead the uid of a
+ // three plane comms based flow factory that can can return a protocol description
+ if(ini->FindVar(protTag, KFilenameItemName, fileName) == EFalse)
+ {
+ // Deal with the flow case
+ // Fetch the UID of the flow factory
+ TInt flowFactoryUid;
+ if(ini->FindVar(protTag, KFlowFactoryUid, flowFactoryUid) == EFalse)
+ {
+#if defined(_DEBUG)
+ LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing 3PC based protocol - no flow factory UID found")));
+ Panic(EBadProtocolDescription);
+#else
+ User::Leave(KErrNotFound);
+#endif
+ }
+
+ // We need the flow factory container in order to instantiate a flow factory with ECOM
+ // Misconfiguration should not kill off c32 in a release build so we simply leave rather than panic
+#if defined(_DEBUG)
+ if(globals->iSubConnectionFlowFactories == NULL)
+ {
+ LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk files - flow factories not yet initialised")));
+ Panic(EBadProtocolDescription);
+ }
+#else
+ User::LeaveIfNull(globals->iSubConnectionFlowFactories);
+#endif
+
+ // Fetch the given factory and fetch the protocol description from it
+ CSubConnectionFlowFactoryBase* flowFactory =
+ static_cast<CSubConnectionFlowFactoryBase*>(globals->iSubConnectionFlowFactories->FindOrCreateFactoryL(TUid::Uid(flowFactoryUid)));
+ CleanupStack::PushL(flowFactory);
+
+ // Fetch the id of the protocol itself (as one factory can create flows of more than one type)
+ TInt protocol;
+ if(ini->FindVar(protTag, KFlowProtocol, protocol) == EFalse)
+ {
+ LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - no 3PC protocol found")));
+ __ASSERT_DEBUG(0, Panic(EBadProtocolDescription));
+ User::Leave(KErrNotFound);
+ }
+
+ // Ask for a protocol description from the flow factory and add that description to our globals
+#if defined(_DEBUG)
+ TServerProtocolDesc* protocolDescription = NULL;
+ TRAPD(descriptionError, protocolDescription = flowFactory->CreateFlowDescriptionL(protocol););
+ if(descriptionError != KErrNone)
+ {
+ LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - no protocol description provided by factory for 3PC based flow type")));
+ Panic(EBadProtocolDescription);
+ }
+#else
+ TServerProtocolDesc* protocolDescription = flowFactory->CreateFlowDescriptionL(protocol);
+#endif
+
+ CleanupStack::PushL(protocolDescription);
+ CProtocolRef::MakeRefL(protTag, protocolDescription);
+ globals->iNumProtocols++;
+ delete protocolDescription;
+
+ CleanupStack::Pop(2, flowFactory);
+ }
+ else
+ {
+ // Deal with the legacy case
+ TPtrC bindfrom(NULL, 0);
+ if (ini->FindVar(protTag,KBindFromItemName,bindfrom))
+ {
+ AddDependencyL(bindfrom, protTag);
+ }
+
+ CProtocolFamilyRef* protFamily = NULL;
+ TInt err;
+ TRAP(err, protFamily = CProtocolFamilyRef::GetProtocolFamilyL(fileName));
+ if (err != KErrNone)
+ {
+ continue;
+ }
+ CleanupStack::PushL(protFamily);
+
+ // Query the protocol family about all the socket types it can produce
+ // We'll remember them because we unload the libraries until we actually need them.
+ TServerProtocolDesc *protocolList = NULL;
+
+
+ // Note: some protocols will leave in their ProtocolList() method. This
+ // is handled correctly here, although the naming convention is incorrect.
+ TInt numProtocols = 0;
+ TRAP(err, numProtocols = protFamily->ProtocolFamilyL(EFalse).ProtocolList(protocolList));
+
+ if (numProtocols == 0 || err != KErrNone)
+ {
+ LOG( ESockLog::Printf(_L("ProtocolManager: Protocol %S failed to load (error = %d, number of protocols = %d)"),
+ &protTag, err, numProtocols) );
+ CleanupStack::Pop(protFamily);
+ continue;
+ }
+
+#if defined (_DEBUG)
+ CheckProtocolList(protocolList,numProtocols);
+#endif
+ CleanupArrayDeletePushL(protocolList);
+ TInt num=0;
+ if (numProtocols>1)
+ {
+ if (ini->FindVar(protTag,KIndexTagName,num) == EFalse)
+ {
+ LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - Protocol index missing")));
+ User::Leave(KErrNotFound);
+ }
+ num--;
+ }
+
+ if (num>numProtocols)
+ {
+ CleanupStack::Pop(protocolList);
+ CleanupStack::Pop(protFamily);
+ continue;
+ }
+
+
+ CProtocolRef *pp=CProtocolRef::MakeRefL(protTag,protFamily,protocolList+num);
+ if (pp==NULL)
+ {
+ User::Leave(KErrNoMemory);
+ }
+ CleanupStack::Pop(protocolList);
+ LOG(ESockLog::Printf(KESockSessDetailTag, _L("ProtocolManager: prot '%S' ref=%08x, famRef=%08x, num=%d"), &protTag, pp, protFamily, num));
+
+ globals->iNumProtocols++;
+
+ delete []protocolList;
+ CleanupStack::Pop(protFamily);
+ }
+ }
+ while (ch!=0); // ch==0 when last token removed from TLex
+
+ // Leave if there's no point in carrying on. - i.e. no protocols.
+ if (globals->iNumProtocols==0)
+ {
+ LOG(ESockLog::Printf(_L("ProtocolManager: No protocols - leaving.")));
+ User::Leave(KErrBadDriver);
+ }
+
+ // Delete all protocolfamilybase objects, causing DLLs to unload
+ LOG(ESockLog::Printf(_L("ProtocolManager: Finished initialising. Unloading all PRTs.")));
+ TSglQueIter<CProtocolFamilyRef> familyIter(*globals->iProtocolFamilies);
+ CProtocolFamilyRef* family;
+ while(family=familyIter++,family!=NULL)
+ {
+ delete &(family->ProtocolFamilyL(EFalse));
+ }
+
+ LOG(ESockLog::Printf(_L("ProtocolManager: Done.")));
+
+ if(globals->iDeps)
+ {
+ LOG(ESockLog::Printf(_L("Dependencies: %S"), &*(globals->iDeps)));
+ }
+ }
+
+void ProtocolManager::SafeCleanupProtocol(TAny* aProtocolRef)
+/**
+Try to clean up a protocol instance
+
+This routine is pushed onto the cleanup stack in order to clean up a protocol instance.
+The check against the protocol pointer being non-NULL is a safety check. This routine was
+created because ProtocolManager::CleanupProtocol(protocol) was being called in circumstances
+where the protocol had already gone and the pointer to it had become invalid. This routine
+takes as argument a pointer to the CProtocolRef instance of the protocol, so that the protocol
+pointer can be checked against NULL.
+
+@param aProtocolRef pointer to the CProtocolRef instance whose protocol needs to be deleted
+*/
+ {
+ CProtocolRef *pRef = reinterpret_cast<CProtocolRef*>(aProtocolRef);
+ if (pRef->Protocol())
+ {
+ pRef->Protocol()->TryDelete();
+ }
+ }
+
+void ProtocolManager::CleanupProtocol(TAny* aProtocol)
+ {
+ ((CProtocolBase *)aProtocol)->TryDelete();
+ }
+
+void ProtocolManager::TransferSocketL(CSocket* aSocket, CPlayer* aPlayer)
+/**
+Transfer socket from one session to another
+*/
+ {
+
+ //-- check the flag that enables socket transfer and the capabilities of the process that owns aSession,
+ //-- where the socket is supposed to be transferred.
+ if(aSocket->iSecTransferEnabled && aSocket->iTransferSecPolicy.CheckPolicy(aPlayer->SafeMessage()))
+ {//-- everything is OK, reset socket transfer flag.
+ aSocket->iSecTransferEnabled = EFalse;
+ }
+ else
+ {//-- security check failed.
+ User::Leave(KErrPermissionDenied);
+ }
+
+ if (aSocket->iSSP)
+ {
+ // For non-null sockets, ask the socket provider to perform security
+ // policy checking on new session
+ User::LeaveIfError(aSocket->iSSP->SecurityCheck(aPlayer->CurrentSession()));
+ }
+
+ // Add the protocol of the socket being transferred to the receipient session's list of protocols
+ // The socket doesn't know about legacy protocols directly anymore so we need to find the protocol
+ TProtocolDesc* info = aSocket->iProtocolInfo;
+ __ASSERT_DEBUG(info, User::Panic(KSpecAssert_ESockSSockS_MAN, 1));
+ CProtocolRef* protocolReference = FindProtocolL(info->iAddrFamily, info->iSockType, info->iProtocol);
+ CProtocolBase* protocol = protocolReference->Protocol();
+
+ // The protocol reference will not have a protocol member if it refers to a new 3PC based flow
+ // Add the protocol to the sessionproxy for the session receiving the socket
+ if(protocol)
+ {
+ aPlayer->CurrentSessionProxyL()->AddProtocolL(protocol);
+ }
+ }
+
+CProtocolBase* ProtocolManager::FindAndLoadProtocolL(const TDesC& aName, TProtocolType aType)
+/**
+Find a protocol by name and load it.
+Caller is responsible for ultimately deleting the protocol
+
+This is for use by extension DLLs as it does not attach the protocol
+to a session.
+
+*/
+ {
+ TServerProtocolDesc pinfo;
+ User::LeaveIfError(ProtocolInfo(aName,pinfo));
+ switch (aType)
+ {
+ case ENormalProtocol:
+ // Dont care what extra interfaces it supports
+ break;
+ case EInterfaceProtocol:
+ // Need a protocol that support Interface extensions
+ if (!(pinfo.iServiceTypeInfo & EInterface))
+ {
+ User::Leave(KErrBadName);
+ }
+ break;
+ }
+ return (FindAndLoadProtocolL(pinfo.iAddrFamily, pinfo.iSockType, pinfo.iProtocol));
+ }
+
+CProtocolBase* ProtocolManager::FindAndLoadProtocolL(TUint aAddrFamily,TUint aSockType,TUint aProtocol)
+/**
+Find a protocol by address family, socket type, and protocol ID and load it.
+Caller is responsible for ultimately deleting the protocol
+
+This is for use by extension DLLs as it does not attach the protocol
+to a session.
+*/
+ {
+ CProtocolRef* pref = FindProtocolL(aAddrFamily,aSockType,aProtocol);
+ pref->LoadAndBindL();
+ return pref->Protocol();
+ }
+
+void ProtocolManager::LoadProtocolL(TUint anAddrFamily, TUint aSocketType, TUint aProtocol, CPlayer* aPlayer)
+/**
+Manually load the specified protocol
+This is used by clients who need to ensure that an open call will not take a
+significant amount of time (e.g. IrCOMM) It effectively makes all the lengthy parts of Open asynchronous.
+
+*/
+ {
+ CProtocolRef* prot = FindProtocolL(anAddrFamily, aSocketType, aProtocol);
+
+ // If the protocol reference is for a "three plane comms" based flow then we silently return
+ // without loading anything as their lifetime is managed by ECOM and therefore explicit loading is not supported
+ if(prot->GetFlag() & CProtocolRef::EThreePlaneCommsBased)
+ {
+ return;
+ }
+
+ // Got one, make sure the library is loaded and we have an instance of the protocol object.
+ prot->LoadAndBindL();
+ CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
+
+ // register the protocol with the Session
+ aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
+ CleanupStack::Pop();
+ }
+
+void ProtocolManager::UnLoadProtocolL(TUint anAddrFamily, TUint aSocketType, TUint aProtocol, CPlayer* aPlayer)
+/**
+Do the opposite of the above function
+
+*/
+ {
+ CProtocolRef* prot = FindProtocolL(anAddrFamily, aSocketType, aProtocol);
+
+ // If the protocol reference is for a "three plane comms" based flow then we silently return
+ // without attempting to unload anything as their lifetime is managed by ECOM only
+ if(prot->GetFlag() & CProtocolRef::EThreePlaneCommsBased)
+ {
+ return;
+ }
+
+ aPlayer->CurrentSessionProxyL()->RemoveProtocolL(prot->Protocol());
+ }
+
+CHostResolver* ProtocolManager::NewHostResolverL(TUint anAddrFamily, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
+/**
+Create a new host resolver object
+
+*/
+ {
+ CProtocolRef * prot=FindProtocolL(anAddrFamily,KUndefinedSockType,aProtocolId);
+ if (!(prot->Info().iNamingServices & KNSNameResolution))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // Got one, make sure protocol & library are loaded
+ prot->LoadAndBindL();
+
+ CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
+
+ CHostResolvProvdBase* hr=prot->Protocol()->NewHostResolverL();
+
+ // Give the host resolver the info to clean up after itself.
+ hr->iProtocol=prot->Protocol();
+
+ CleanupStack::Pop();
+ CleanupStack::PushL(hr);
+
+
+ // ask the resolver provider to perform security policy checking
+ User::LeaveIfError(hr->SecurityCheck(aPlayer->CurrentSession()));
+ CHostResolver* r=CHostResolver::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
+
+// CleanupStack::PushL(r);
+
+
+// CleanupStack::Pop(r);
+// CleanupStack::PushL(TCleanupItem(CloseSubSession,r));
+
+ // register the protocol with the Session
+// aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
+
+ aPlayer->SubSessions().AppendL(r);
+ hr->SetNotify(r);
+ r->SetResolver(hr);
+ CleanupStack::Pop(r);
+ CleanupStack::Pop(hr);
+// CleanupStack::Pop(1);
+
+ return r;
+ }
+
+CServiceResolver* ProtocolManager::NewServiceResolverL(TUint anAddrFamily, TUint aSocketType, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
+/**
+Create a new service resolver provider
+
+*/
+ {
+ CProtocolRef * prot=FindProtocolL(anAddrFamily,aSocketType,aProtocolId);
+ if (!(prot->Info().iNamingServices & KNSServiceResolution))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // Got one, make sure protocol & library are loaded
+ prot->LoadAndBindL();
+ CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
+
+ CServiceResolvProvdBase *sr=NULL;
+
+ sr=prot->Protocol()->NewServiceResolverL();
+ CleanupStack::PushL(sr);
+
+ // Give the host resolver the info to clean up after itself.
+ sr->iProtocol=prot->Protocol();
+
+ // ask the resolver provider to perform security policy checking
+ User::LeaveIfError(sr->SecurityCheck(aPlayer->CurrentSession()));
+ CServiceResolver* s=CServiceResolver::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
+ sr->SetNotify(s);
+
+// CleanupStack::PushL(TCleanupItem(CloseSubSession,s));
+
+ // register the protocol with the Session
+// aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
+
+ aPlayer->SubSessions().AppendL(s);
+ s->SetResolver(sr);
+
+ CleanupStack::Pop(3);
+ return s;
+ }
+
+CNetDatabase* ProtocolManager::NewNetDatabaseL(TUint anAddrFamily, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
+/**
+Create a new database type thang
+
+*/
+ {
+ CProtocolRef * prot=FindProtocolL(anAddrFamily,KUndefinedSockType,aProtocolId);
+ if (!(prot->Info().iNamingServices & KNSInfoDatabase))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // Got one, make sure protocol & library are loaded
+ prot->LoadAndBindL();
+ CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
+
+ CNetDBProvdBase *db=NULL;
+ db=prot->Protocol()->NewNetDatabaseL();
+
+ CleanupStack::PushL(db);
+
+ // Give the host resolver the info to clean up after itself.
+ db->iProtocol=prot->Protocol();
+
+ // ask the net database provider to perform security policy checking
+ User::LeaveIfError(db->SecurityCheck(aPlayer->CurrentSession()));
+
+ CNetDatabase* n=CNetDatabase::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
+ db->SetNotify(n);
+// CleanupStack::Pop();
+
+// CleanupStack::PushL(TCleanupItem(CloseSubSession,n));
+
+ // register the protocol with the Session
+// aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
+
+ aPlayer->SubSessions().AppendL(n);
+ n->SetProvd(db);
+
+ CleanupStack::Pop(3);
+ return n;
+ }
+
+CInternalSocketImpl* ProtocolManager::NewInternalSocketL ( TAny* aParams, const TDesC& aName )
+ {
+ TServerProtocolDesc pinfo;
+ User::LeaveIfError(ProtocolInfo(aName,pinfo));
+ return ProtocolManager::NewInternalSocketL ( aParams, pinfo.iAddrFamily, pinfo.iSockType, pinfo.iProtocol );
+ }
+
+CInternalSocketImpl* ProtocolManager::NewInternalSocketL ( TAny* aParams, TUint aAddrFamily, TUint aSockType, TUint aProtocol )
+ {
+ CInternalSockSubSession::TParameters* params = reinterpret_cast < CInternalSockSubSession::TParameters* > ( aParams );
+ CProtocolRef* prot = FindProtocolL ( aAddrFamily, aSockType, aProtocol );
+ if (!(prot->Info().iServiceTypeInfo&ESocketSupport))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ prot->LoadAndBindL ();
+ // Please check @NewSocketL to see why we need to push this item.
+ CleanupStack::PushL ( TCleanupItem ( ProtocolManager::CleanupProtocol,prot->Protocol () ) );
+ CInternalSocketImpl* intSock = CInternalSocketImpl::NewL ( *params, &( prot->Info() ), prot->Protocol() );
+ CleanupStack::Pop (); // prot
+ return intSock;
+ }
+
+TUint ProtocolManager::NumProtocols(void)
+ {
+
+ return SockManGlobals::Get()->iNumProtocols;
+ }
+
+TInt ProtocolManager::ProtocolInfo(const TDesC &aName,TProtocolDesc &aProtocol)
+ {
+ TInt ret;
+ TServerProtocolDesc info;
+
+ ret = ProtocolInfo(aName, info);
+ if (ret==KErrNone)
+ {
+ aProtocol = info;
+ }
+ return ret;
+ }
+
+
+TInt ProtocolManager::ProtocolInfo(const TDesC &aName,TServerProtocolDesc &aProtocol)
+/**
+Find a protocol by name - no wildcard support.
+
+*/
+ {
+ TSglQueIter<CProtocolRef> i(*SockManGlobals::Get()->iProtocols);
+
+ // Run the queue looking for a match.
+ do
+ {
+ if(((CProtocolRef *)i)->Info().iName.Compare(aName)==0)
+ {
+ aProtocol=((CProtocolRef*)i)->Info();
+ return KErrNone;
+ }
+ i++;
+ }
+ while((CProtocolRef *)i);
+
+ return KErrNotFound;
+ }
+
+
+CProtocolRef* ProtocolManager::FindProtocolL(TInt anAddrFamily,TUint aSocketType,TInt aProtocol)
+/**
+ Find a protocol from the lists.
+*/
+ {
+
+ TSglQueIter<CProtocolRef> i(*SockManGlobals::Get()->iProtocols);
+
+ CProtocolRef *pP;
+ // Run the protocol queue looking for a match on requested socket type.
+ while ((pP=i++)!=NULL)
+ {
+ if (pP->Matches(anAddrFamily,aSocketType,aProtocol))
+ {
+ return pP;
+ }
+ }
+
+ User::Leave(KErrBadName);
+ return NULL; //lint !e527 // LINT knows we can't get here
+ }
+
+
+CProtocolFamilyRef::CProtocolFamilyRef()
+ :CBase()
+ {
+ }
+
+CProtocolFamilyRef::~CProtocolFamilyRef()
+ {
+ if (iLibFileName)
+ {
+ delete iLibFileName;
+ }
+ }
+
+CProtocolFamilyRef* CProtocolFamilyRef::GetProtocolFamilyL(TDesC& aName)
+/**
+Either return a pointer to an existing protocol ref or create a new one.
+
+*/
+ {
+
+ TSglQue<CProtocolFamilyRef>* families=SockManGlobals::Get()->iProtocolFamilies;
+ TSglQueIter<CProtocolFamilyRef> i(*families);
+
+ // Run through the list of existing protocols looking for a match.
+ CProtocolFamilyRef* protRef;
+ while(protRef=(CProtocolFamilyRef *)i,protRef)
+ {
+ if(protRef->iLibFileName->Compare(aName)==0)
+ {
+ if (protRef->iProtocolFamily)
+ {
+ return protRef;
+ }
+ else
+ {
+ break;
+ }
+ }
+ i++;
+ }
+
+ // Not found one yet - we must create one.
+ if (!protRef)
+ {
+ protRef=new(ELeave) CProtocolFamilyRef;
+ CleanupStack::PushL(protRef);
+ protRef->iLibFileName=aName.AllocL();
+
+ // Ensure that this protocol we're about to return is loaded
+ protRef->LoadL();
+
+ // If it didn't leave, then add it to the list
+ families->AddLast(*protRef);
+ }
+ else
+ {
+ CleanupStack::PushL(protRef);
+ // Ensure that this protocol we're about to return is loaded
+ protRef->LoadL();
+ }
+
+ CleanupStack::Pop();
+
+ return protRef;
+ }
+
+void CProtocolFamilyRef::LoadL()
+/**
+Load the protocol. Leave it un-initted until the last minute - i.e. init it in the accessor.
+
+*/
+ {
+ if (iProtocolFamily)
+ {
+ return;
+ }
+
+ TAutoClose<RLibrary> lib;
+ const TInt ret = lib.iObj.Load(*iLibFileName);
+ LOG(TBuf8<64> buf8);
+ LOG(buf8.Copy(iLibFileName->Des()));
+ LOG(ESockLog::Printf(KESockProvChoresTag, _L8("CProtocolFamilyRef(%08x)::LoadL '%S' [ret=%d]"), this, &buf8, ret));
+ if(ret!=KErrNone)
+ {
+ delete iLibFileName; // cleanup after aName.AllocL
+ iLibFileName = NULL;
+ User::Leave(ret);
+ }
+ lib.PushL();
+
+ // The Uid check
+#ifdef _UNICODE
+ if(lib.iObj.Type()[1]!=TUid::Uid(KUidUnicodeProtocolModule))
+ {
+ LOG(ESockLog::Printf(_L8("FAILED uid check! (type=%08X)"), lib.iObj.Type()[1].iUid));
+ User::Leave(KErrBadLibraryEntryPoint);
+ }
+#else
+ if(lib.iObj.Type()[1]!=TUid::Uid(KUidProtocolModule))
+ {
+ User::Leave(KErrBadLibraryEntryPoint);
+ }
+#endif
+
+ TProtocolNew libEntry=(TProtocolNew)lib.iObj.Lookup(1);
+ if (libEntry==NULL)
+ {
+ LOG(ESockLog::Printf(_L8("FAILED retrieving factory entrypoint (ord 1)")));
+ User::Leave(KErrNoMemory);
+ }
+
+ iProtocolFamily=(*libEntry)();
+ if (!iProtocolFamily)
+ {
+ LOG(ESockLog::Printf(_L8("FAILED running factory entrypoint")));
+ User::Leave(KErrNoMemory);
+ }
+
+ // Make sure the protocol family has all the info needed to clean up after itself.
+ iProtocolFamily->iManagerRef=this;
+ TRAPD(res, iProtocolFamily->SetLibraryL(lib.iObj));
+ if(res != KErrNone)
+ {
+ LOG(ESockLog::Printf(_L8("FAILED creating lib unloader (err %d)"), res));
+ delete iProtocolFamily;
+ iProtocolFamily=0;
+ User::Leave(res);
+ }
+
+ lib.Pop();
+ lib.iObj.SetHandle(0); // Dont let ~TAutoClose() close library
+ }
+
+CProtocolFamilyBase& CProtocolFamilyRef::ProtocolFamilyL(TBool aInstall)
+/**
+Accessor to ProtocolFamily from manager ref - this must leave because we perform late loading and
+hence must allocate memory and other nasty grubby things.
+
+*/
+ {
+ if (!iProtocolFamily)
+ {
+ LoadL();
+ }
+ __ASSERT_DEBUG(iProtocolFamily, User::Panic(KSpecAssert_ESockSSockS_MAN, 2));
+
+ if (aInstall && !(iFlags&EInstalled))
+ {
+ TInt r=iProtocolFamily->Install();
+ if (r!=KErrNone)
+ {
+ delete iProtocolFamily;
+ iProtocolFamily=0;
+ User::Leave(r);
+ }
+ iFlags|=EInstalled;
+ }
+
+ return *iProtocolFamily;
+ }
+
+CProtocolRef::~CProtocolRef()
+ {
+ delete iTag;
+ }
+
+CProtocolRef::CProtocolRef()
+ :CBase()
+ {
+ }
+
+TBool CProtocolRef::Matches(TUint anAddrFamily,TUint aSockType,TUint aProtocol)
+/**
+Return ETrue if a protocol desc matches the specified family type and protocol
+We allow clients to be a little hazy about their exact requirements
+
+*/
+ {
+ if(iInfo.iAddrFamily==anAddrFamily &&
+ (iInfo.iSockType==KUndefinedSockType || aSockType==KUndefinedSockType || iInfo.iSockType==aSockType) &&
+ (iInfo.iProtocol==KUndefinedProtocol || aProtocol==KUndefinedProtocol || iInfo.iProtocol==aProtocol))
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+CProtocolRef* CProtocolRef::GetProtocolNoCreate(TProtocolRefList *iProtocolList, const TDesC& aTag)
+/**
+Find a protocol from the lists by name
+Return null if not found;
+*/
+ {
+ TSglQueIter<CProtocolRef> i(*iProtocolList);
+
+ CProtocolRef *pP = NULL;
+ // Run the protocol queue looking for a match on requested name
+ while ((pP=i++)!=NULL)
+ {
+ if (pP->iTag->Compare(aTag)==0)
+ {
+ return pP;
+ }
+ }
+ return NULL;
+ }
+
+CProtocolRef* CProtocolRef::GetProtocolL(const TDesC& aTag)
+/**
+Find a protocol from the lists by name
+Will make a new ref and families if required.
+
+*/
+ {
+ TSglQue<CProtocolRef>* protocols=SockManGlobals::Get()->iProtocols;
+
+
+ CProtocolRef *pP = GetProtocolNoCreate(protocols,aTag);
+
+ if (!pP)
+ {
+ pP=MakeRefL(aTag);
+ }
+
+ return pP;
+ }
+
+void CProtocolRef::Cleanup(TAny* aFamily)
+/**
+Close a protocol family from the cleanup stack.
+
+*/
+ {
+ ((CProtocolFamilyRef *)aFamily)->Close();
+ }
+
+void CloseProtocol(TAny* aProtocol)
+ {
+ ((CProtocolBase*)aProtocol)->Close();
+ }
+void BindingLeave(TAny* aProtRef)
+ {
+ TUint flag=((CProtocolRef*)aProtRef)->GetFlag();
+ ((CProtocolRef*)aProtRef)->SetFlag(~(CProtocolRef::EBound) & flag);
+ }
+
+void CProtocolRef::LoadL(TBool aLoadForBinding)
+/**
+Fill in a protocol ref - loading any libs or families
+Loads and binds the requested protocol loading any libraries required.
+May go recursive if a bindee needs loading and the aloadForBinding argument is set.
+
+*/
+ {
+ if (iProtocol)
+ {
+ if (!aLoadForBinding)
+ {
+ CleanupStack::PushL(TCleanupItem(BindingLeave, this));
+ ResolveBindingL();
+ CleanupStack::Pop();
+ }
+ return;
+ }
+
+ // Three plane comms protos shouldn't be loading like this
+ __ASSERT_DEBUG(! (GetFlag() & CProtocolRef::EThreePlaneCommsBased), User::Panic(KSpecAssert_ESockSSockS_MAN, 3));
+
+ __ASSERT_DEBUG(iFamily, User::Panic(KSpecAssert_ESockSSockS_MAN, 4));
+ iFamily->ProtocolFamilyL().Open();
+
+ CleanupStack::PushL(TCleanupItem(CProtocolRef::Cleanup,iFamily));
+
+ // Get the Protocol from the family
+ iProtocol=iFamily->ProtocolFamilyL().NewProtocolL(iInfo.iSockType,iInfo.iProtocol);
+
+ // At this stage the iProtocol member effectively takes over control of closing
+ // the family reference
+ // Note there is a work around in TCPIP 047 which fixes the problem
+ // by pushing a NULL reference
+ CleanupStack::Pop();
+
+ // Make sure the protocol has the info needed to clean up after itself.
+ iProtocol->iManagerRef=this;
+
+ CleanupStack::PushL(iProtocol);
+ if (!(iFlags & EInited))
+ {
+ iProtocol->InitL(*iTag);
+ iFlags|=EInited;
+ }
+
+ if (!aLoadForBinding)
+ {
+ ResolveBindingL();
+ }
+
+ CleanupStack::Pop(1); // Was pop(2) see comment above
+ }
+
+void CProtocolRef::ResolveBindingL()
+/**
+Resolve binding requirements for a top level (i.e service provider) protocol
+
+*/
+ {
+ if (iFlags&EBound)
+ {
+ return;
+ }
+
+ LoadL(ETrue);
+// CESockIniData* ini=CESockIniData::NewL();
+// CleanupStack::PushL(ini);
+
+ const CESockIniData* ini=SockManGlobals::Get()->IniData();
+ DoBindingL(*ini);
+// CleanupStack::PopAndDestroy(ini);
+
+ iFlags|=EBound;
+ }
+
+
+void CProtocolRef::DoBindingL(const CESockIniData& aIniFile)
+/**
+ Actually perform the binding for a given protocol. Recursive
+*/
+ {
+ if (iFlags&EBound)
+ {
+ return;
+ }
+
+ iFlags|=EBound; // Set "is bound" flag here to preempt any recursive binding.
+
+ TPtrC bindList;
+ if (aIniFile.FindVar(*iTag,KBindToItemName,bindList))
+ {
+ // BindTo scenario. Proceed with the node current node is binding to
+ ProcessBindListL(bindList, aIniFile);
+ }
+
+ TPtrC depList;
+ TBool foundDep = ProtocolManager::GetDependency(*iTag,depList);
+ if(foundDep)
+ {
+ // BindFrom scenario. Proceed with the node that is binding from to current one
+ ProcessBindListL(depList, aIniFile);
+ }
+
+ StartL();
+ }
+
+void CProtocolRef::ProcessBindListL(TPtrC aBindList, const CESockIniData& aIniFile)
+ {
+ LOG( ESockLog::Printf(_L("ProcessBindListL(aBindList = %S)"), &aBindList) );
+ TLex lex(aBindList);
+ TChar ch=0;
+ do
+ {
+ lex.Mark();
+ do
+ {
+ ch=lex.Get();
+ }
+ while (ch!=',' && ch!=0);
+
+ if (ch==',')
+ {
+ lex.UnGet();
+ }
+
+ CProtocolRef* prot=GetProtocolL(lex.MarkedToken());
+ lex.Get();
+ prot->LoadL(ETrue);
+ prot->iProtocol->Open();
+
+ CleanupStack::PushL(TCleanupItem(CloseProtocol, prot->iProtocol));
+ CleanupStack::PushL(TCleanupItem(BindingLeave, prot));
+
+ prot->DoBindingL(aIniFile);
+ prot->StartL();
+
+ LOG_STMT(TPtrC bindFrom = iProtocol->Tag();)
+ LOG_STMT(TPtrC bindTo = prot->iProtocol->Tag();)
+ LOG( ESockLog::Printf(_L("ProcessBindListL(Binding: %S -> %S)"), &bindFrom, &bindTo) );
+
+ iProtocol->BindToL(prot->iProtocol);
+
+ CleanupStack::Pop();
+ CleanupStack::PopAndDestroy();
+ }
+ while (ch!=0); // ch == 0 when last token extracted from TLex
+ }
+
+
+CProtocolRef* CProtocolRef::MakeRefL(const TDesC& aTag,CProtocolFamilyRef* aFamily,TServerProtocolDesc* anInfo)
+/**
+Protocol reference 'constructor'.
+CProtocolRef really is a refernece and hence it runs the list of currently loaded protocols
+before really and truly loading
+
+*/
+ {
+ CProtocolRef* pP=new(ELeave) CProtocolRef;
+ CleanupStack::PushL(pP);
+ pP->iTag=aTag.AllocL();
+
+ if (aFamily==NULL && anInfo==NULL)
+ {
+ TPtrC familyName(NULL,0);
+
+ const CESockIniData* ini=SockManGlobals::Get()->IniData();
+ if (!ini->FindVar(aTag,KFilenameItemName,familyName))
+ {
+ User::Leave(KErrBadName);
+ }
+ pP->iFamily=CProtocolFamilyRef::GetProtocolFamilyL(familyName);
+
+ TServerProtocolDesc* protocolList;
+ TInt numProtocols=pP->iFamily->ProtocolFamilyL().ProtocolList(protocolList);
+ TInt index=0;
+
+ if (numProtocols>1 && !ini->FindVar(aTag,KIndexTagName,index))
+ {
+ User::Leave(KErrBadName);
+ }
+
+ pP->iInfo=protocolList[index-1];
+ delete[] protocolList;
+ }
+ else
+ {
+ pP->iInfo=*anInfo;
+ pP->iFamily=aFamily;
+ }
+
+ TSglQue<CProtocolRef>* protList = SockManGlobals::Get()->iProtocols;
+#ifdef _DEBUG
+ CProtocolRef* ref = GetProtocolNoCreate(protList,aTag);
+ if (ref) // uhoh we have a duplicate protocol better panic in debug mode
+ {
+ LOG( ESockLog::Printf(_L("ERROR in config - duplicate protocol loaded: %S loaded more than once"),&aTag));
+ Panic(EBadProtocolDescription);
+ }
+#endif
+ protList->AddLast(*pP);
+ CleanupStack::Pop(pP);
+ return pP;
+ }
+
+CProtocolRef* CProtocolRef::MakeRefL(const TDesC& aName, TServerProtocolDesc* aInfo)
+/**
+Protocol reference 'constructor'.
+This overload of is for "three plane comms" based flows only. It creates a protocol reference
+that is then not subject to particular requirements of legacy protocols such as explicit
+loading with `RSocketServ::StartProtocol()`
+*/
+ {
+ __ASSERT_DEBUG(aInfo, Panic(EBadProtocolDescription));
+ User::LeaveIfNull(aInfo);
+
+ // Create our protocol reference and designate it as being 3PC based
+ CProtocolRef* pP = new(ELeave) CProtocolRef;
+ pP->SetFlag(EThreePlaneCommsBased);
+
+ CleanupStack::PushL(pP);
+ pP->iTag = aName.AllocL();
+ pP->iInfo = *aInfo;
+ pP->iFamily = NULL;
+
+ // Now add it to our global list of protocols
+ TSglQue<CProtocolRef>* protList = SockManGlobals::Get()->iProtocols;
+
+#ifdef _DEBUG
+ CProtocolRef* ref = GetProtocolNoCreate(protList, aName);
+ if (ref) // uhoh we have a duplicate protocol better panic in debug mode
+ {
+ LOG( ESockLog::Printf(_L("ERROR in config - duplicate protocol loaded: %S loaded more than once"), &aName));
+ Panic(EBadProtocolDescription);
+ }
+#endif
+
+ protList->AddLast(*pP);
+ CleanupStack::Pop(pP);
+ return pP;
+ }
+
+
+void CProtocolRef::StartL()
+/**
+Start the protocol - only once mind lad.
+
+*/
+ {
+ if (!(iFlags&EStarted))
+ {
+ iProtocol->StartL();
+ iFlags|=EStarted;
+ }
+ }
+
+#ifdef __FLOG_ACTIVE
+
+void TProtocolManagerLogger::LogLoadedInfo()
+ {
+ CSockManData* globals=SockManGlobals::Get();
+ TBuf<256> descList;
+ TLogIgnoreOverflow16 overflow;
+
+ TSglQueIter<CProtocolFamilyRef> j(*globals->iProtocolFamilies);
+ CProtocolFamilyRef* f=NULL;
+ while(f=j++,f!=NULL)
+ {
+ if(f->iProtocolFamily)
+ {
+ descList.AppendFormat(_L(" %08x,"), &overflow, f->iProtocolFamily);
+ }
+ }
+ LOG( ESockLog::Printf(_L("Families (addr):%S"), &descList) );
+
+ descList.SetLength(0);
+ TSglQueIter<CProtocolRef> i(*globals->iProtocols);
+ CProtocolRef* p=NULL;
+ while(p=i++,p!=NULL)
+ {
+ if(p->Protocol())
+ {
+ const TDesC& tag(p->Tag());
+ descList.AppendFormat(_L(" %S[%08x],"), &overflow, &tag, p->Family());
+ }
+ }
+ LOG( ESockLog::Printf(_L("Protocols + fam addr:%S"), &descList) );
+ }
+
+#endif