datacommsserver/esockserver/ssock/SS_MAN.CPP
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <comms-infras/ss_roles.h>
       
    17 #include <ss_glob.h>
       
    18 //#include <es_ini.h>
       
    19 #include <comms-infras/ss_log.h>
       
    20 #include <ss_protprov.h>
       
    21 #include <comms-infras/ss_sapshim.h>
       
    22 #include <ss_sock.h>
       
    23 #include "SS_rslv.H"
       
    24 #include "SS_conn.H"
       
    25 #include "ss_eintsockimpl.h"
       
    26 
       
    27 
       
    28 #ifdef _DEBUG
       
    29 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    30 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    31 _LIT(KSpecAssert_ESockSSockS_MAN, "ESockSSockS_MAN.");
       
    32 #endif
       
    33 
       
    34 using namespace ESock;
       
    35 
       
    36 #if defined (_DEBUG)
       
    37 
       
    38 /** @file
       
    39 Check that the protocol has filled in the protocol structure
       
    40 As much as we can anyway.
       
    41 Note that this function needs to be maintained in parallel with the contents of es_sock.h and es_prot.h
       
    42 
       
    43 A panic in this function means that the protocol has returned an invalid TServerProtocolDesc
       
    44 
       
    45 @internalComponent
       
    46 */
       
    47 void CheckProtocolList(TServerProtocolDesc* aProtocolList,TInt aCount)
       
    48 	{
       
    49 	for (TInt i=0;i<aCount;i++)
       
    50 		{
       
    51 		if ((aProtocolList+i)->iServiceTypeInfo&0xFFFFFF00)
       
    52 			{
       
    53 			Panic(EBadProtocolDescription);
       
    54 			}
       
    55 		if ((aProtocolList+i)->iNumSockets==(TInt)0xa5a5a5a5)
       
    56 			{
       
    57 			Panic(EBadProtocolDescription);
       
    58 			}
       
    59 		if ((aProtocolList+i)->iName.Length()==0)
       
    60 			{
       
    61 			Panic(EBadProtocolDescription);
       
    62 			}
       
    63 		if ((aProtocolList+i)->iAddrFamily==0 || (aProtocolList+i)->iAddrFamily==0xa5a5a5a5)
       
    64 			{
       
    65 			Panic(EBadProtocolDescription);
       
    66 			}
       
    67 		if ((aProtocolList+i)->iSockType==0xa5a5a5a5)
       
    68 			{
       
    69 			Panic(EBadProtocolDescription);
       
    70 			}
       
    71 		//If the socket has no support for sockets (NumSockets is 0)
       
    72 		//then it should be of SockType 0.
       
    73 		if ((aProtocolList+i)->iSockType==0)
       
    74 			{
       
    75 			if ((aProtocolList+i)->iNumSockets!=0)
       
    76 				{
       
    77 				Panic(EBadProtocolDescription);
       
    78 				}
       
    79 			}
       
    80 		if ((aProtocolList+i)->iProtocol==0 || (aProtocolList+i)->iProtocol==0xa5a5a5a5)
       
    81 			{
       
    82 			Panic(EBadProtocolDescription);
       
    83 			}
       
    84 		if ((((aProtocolList+i)->iVersion.iMajor==0)&&((aProtocolList+i)->iVersion.iMinor==0)&&((aProtocolList+i)->iVersion.iBuild==0)))
       
    85 			{
       
    86 			Panic(EBadProtocolDescription);
       
    87 			}
       
    88 		if (((aProtocolList+i)->iByteOrder!=EBigEndian && (aProtocolList+i)->iByteOrder!=ELittleEndian && (aProtocolList+i)->iByteOrder!=EOtherByteOrder))
       
    89 			{
       
    90 			Panic(EBadProtocolDescription);
       
    91 			}
       
    92 		if ((aProtocolList+i)->iServiceInfo&0xfffc0000)
       
    93 			{
       
    94 			Panic(EBadProtocolDescription);
       
    95 			}
       
    96 		if ((aProtocolList+i)->iNamingServices&0xfffffe00)
       
    97 			{
       
    98 			Panic(EBadProtocolDescription);
       
    99 			}
       
   100 		if ((aProtocolList+i)->iSecurity&0xfffffffe)
       
   101 			{
       
   102 			Panic(EBadProtocolDescription);
       
   103 			}
       
   104 		if (((aProtocolList+i)->iMessageSize<0 && (aProtocolList+i)->iMessageSize!=KSocketMessageSizeNoLimit))
       
   105 			{
       
   106 			Panic(EBadProtocolDescription);
       
   107 			}
       
   108 		}
       
   109 	}
       
   110 #endif
       
   111 
       
   112 //
       
   113 // Protocol manager assumes that there will be an ini file setion called
       
   114 // [protocols] which will contain a single entry: protocols= the data for
       
   115 // which is a comma seperated list of further section names.
       
   116 // Each of these section names should contina a file name of a .PRT
       
   117 // and index number of the protocol inside this family and an optional
       
   118 // bindto= entry specifying which lower protocols this should be bound to.
       
   119 //
       
   120 // The protocol manager late loads (and binds) all protocols - keeping only CProtocolRef etc.
       
   121 // classes which contain enough data to reload the protocol when the first socket is
       
   122 // created. Protocols will the stay loaded unti lthe last client (who made a socket of
       
   123 // the specified type) closes. I.e. protocols are created for sockets but referenced by
       
   124 // sessions.
       
   125 //
       
   126 
       
   127 /**
       
   128 @internalComponent
       
   129 */
       
   130 
       
   131 _LIT(KSockManMainSectionName,"sockman");
       
   132 _LIT(KProtocolListItemName,"protocols");
       
   133 _LIT(KFilenameItemName,"filename");
       
   134 _LIT(KIndexTagName,"index");
       
   135 _LIT(KBindToItemName,"bindto");
       
   136 _LIT(KBindFromItemName,"bindfrom");
       
   137 _LIT(KFlowFactoryUid, "flow_factory_uid");
       
   138 _LIT(KFlowProtocol, "flow_protocol_id");
       
   139 _LIT(KOpenAngle, "<");
       
   140 _LIT(KCloseAngle, ">");
       
   141 _LIT(KComma, ",");
       
   142 
       
   143 const TInt KDependSize = 32;
       
   144 
       
   145 
       
   146 void ProtocolManager::AddDependencyL(const TDesC& aDependentsList, const TDesC& aModuleToLoad)
       
   147 /**
       
   148 Adds a module to the dependency list. Dependency list is of form <a>b,c<d>e,f
       
   149 meaning that module "a" is dependant on "b" and "c" and requires module b and c to be loaded.
       
   150 
       
   151 @param aDependentsList list of dependant components to be loaded
       
   152 @param aModuleToLoad The module for which the dependency is added
       
   153 */
       
   154 	{
       
   155 	CSockManData *globals=SockManGlobals::Get();
       
   156 
       
   157 	if (globals->iDeps == NULL)
       
   158 		{
       
   159 		globals->iDeps = HBufC::NewL(KDependSize);
       
   160 		}
       
   161 
       
   162 	TLex lex(aDependentsList);
       
   163 	TChar ch=0;
       
   164 	do
       
   165 		{
       
   166 		lex.Mark();
       
   167 
       
   168 		do
       
   169 			{
       
   170 			ch=lex.Get();
       
   171 			}
       
   172 		while (ch!=',' && ch!=0);
       
   173 
       
   174 		if (ch==',')
       
   175 			{
       
   176 			lex.UnGet();
       
   177 			}
       
   178 
       
   179 		TPtrC dependent=lex.MarkedToken();
       
   180 		lex.Get();
       
   181 
       
   182 		TBuf<50> searchBuf;
       
   183 		searchBuf.Append(KOpenAngle);
       
   184 		searchBuf.Append(dependent);
       
   185 		searchBuf.Append(KCloseAngle);
       
   186 
       
   187 		TPtr list = globals->iDeps->Des();
       
   188 		TInt reqLength = list.Length() + searchBuf.Length() + aModuleToLoad.Length();
       
   189 		if (reqLength >= list.MaxLength())
       
   190 			{
       
   191 			globals->iDeps = globals->iDeps->ReAllocL(reqLength);
       
   192 			list.Set(globals->iDeps->Des());
       
   193 			}
       
   194 
       
   195 		TInt pos = list.Find(searchBuf);
       
   196 		if (pos == KErrNotFound)
       
   197 			{
       
   198 			list.Append(searchBuf);
       
   199 			list.Append(aModuleToLoad);
       
   200 			}
       
   201 		else
       
   202 			{
       
   203 			pos++;
       
   204 			TInt endPos = list.Mid(pos).Find(KOpenAngle);
       
   205 			if (endPos != KErrNotFound)
       
   206 				{
       
   207 				endPos += pos;
       
   208 				list.Insert(endPos, KComma);
       
   209 				list.Insert(endPos + 1, aModuleToLoad);
       
   210 				}
       
   211 			else
       
   212 				{
       
   213 				list.Append(KComma);
       
   214 				list.Append(aModuleToLoad);
       
   215 				}
       
   216 			}
       
   217 		} while (ch != 0);
       
   218 	}
       
   219 
       
   220 TBool ProtocolManager::GetDependency(const TDesC& aTag,TPtrC &aList)
       
   221 /**
       
   222 Goes through the dependency list and gets the dependant modules for aTag
       
   223 
       
   224 @param aTag The protocol tag based on which the dependancy list is searched
       
   225 @param aList A list of components dependant on aTag protocol which are returned
       
   226 @return ETrue if a dependency for the component aTag is found else EFalse
       
   227 */
       
   228 	{
       
   229 	CSockManData *globals=SockManGlobals::Get();
       
   230 
       
   231 	if(globals->iDeps)
       
   232 		{
       
   233 
       
   234 		TPtrC list = *globals->iDeps;
       
   235 
       
   236 	  	TBuf<50> tag(KOpenAngle);
       
   237 		tag.Append(aTag);
       
   238 		tag.Append(KCloseAngle);
       
   239 
       
   240 		TInt offset= list.Find(tag);
       
   241 
       
   242 		if(offset!=KErrNotFound)
       
   243 			{
       
   244 			aList.Set(list.Mid(offset+tag.Length()));
       
   245 			offset= aList.Find(KOpenAngle);
       
   246 			if(offset!=KErrNotFound)
       
   247 				{
       
   248 				aList.Set(aList.Mid(0,offset));
       
   249 				}
       
   250 			return ETrue;
       
   251 			}
       
   252 		}
       
   253 	return EFalse;
       
   254 	}
       
   255 
       
   256 void ProtocolManager::InitL()
       
   257 /**
       
   258 Init data structures and hunt for protocols.
       
   259 */
       
   260 	{
       
   261 	LOG( ESockLog::Printf(_L("ProtocolManager: Initialising.")) );
       
   262 
       
   263 	// Allocate global storage to be held in tls.
       
   264 	CSockManData *globals=SockManGlobals::Get();
       
   265 
       
   266 	globals->iProtocols=new(ELeave) TSglQue<CProtocolRef>(_FOFF(CProtocolRef,iLink));
       
   267 	CleanupStack::PushL(globals->iProtocols);
       
   268 	globals->iProtocolFamilies=new(ELeave) TSglQue<CProtocolFamilyRef>(_FOFF(CProtocolFamilyRef,iLink));
       
   269 	CleanupStack::Pop(globals->iProtocols);
       
   270 	}
       
   271 
       
   272 void ProtocolManager::ShutDown()
       
   273 /**
       
   274 free data structures
       
   275 */
       
   276 	{
       
   277 	CSockManData* globals=SockManGlobals::Get();
       
   278 
       
   279 	TSglQueIter<CProtocolRef> i(*globals->iProtocols);
       
   280 	CProtocolRef* p=NULL;
       
   281 	while(p=i++,p!=NULL)
       
   282 		{
       
   283 		globals->iProtocols->Remove(*p);
       
   284 		delete p;
       
   285 		}
       
   286 
       
   287 	TSglQueIter<CProtocolFamilyRef> j(*globals->iProtocolFamilies);
       
   288 	CProtocolFamilyRef* f=NULL;
       
   289 	while(f=j++,f!=NULL)
       
   290 		{
       
   291 		globals->iProtocolFamilies->Remove(*f);
       
   292 		delete f;
       
   293 		}
       
   294 
       
   295 	// delete all the containers and lists of protocols etc.
       
   296 	delete globals->iProtocols;
       
   297 	delete globals->iProtocolFamilies;
       
   298 	delete globals->iDeps;
       
   299 
       
   300 	}
       
   301 
       
   302 void ProtocolManager::ProcessIniDataL()
       
   303 	{
       
   304 	LOG( ESockLog::Printf(_L("ProtocolManager: Retrieve ESock inidata.")) );
       
   305 
       
   306 	CSockManData *globals=SockManGlobals::Get();
       
   307 	const CESockIniData* ini=globals->IniData();
       
   308 
       
   309 	TPtrC protocols;
       
   310 	if (ini->FindVar(KSockManMainSectionName,KProtocolListItemName,protocols)==EFalse)
       
   311 		User::Leave(KErrBadName);
       
   312 
       
   313 	LOG( ESockLog::Printf(_L("ProtocolManager: Protocol list is %S"), &protocols) );
       
   314 	LOG( ESockLog::Printf(_L("ProtocolManager: Loading PRTs and setting up protocols.")) );
       
   315 
       
   316 	TLex lex(protocols);
       
   317 	TChar ch=0;
       
   318 	do
       
   319 		{
       
   320 		lex.Mark();
       
   321 
       
   322 		do
       
   323 			{
       
   324 			ch=lex.Get();
       
   325 			}
       
   326 		while (ch!=',' && ch!=0);
       
   327 
       
   328 		if (ch==',')
       
   329 			{
       
   330 			lex.UnGet();
       
   331 			}
       
   332 		TPtrC protTag=lex.MarkedToken();
       
   333 		lex.Get();
       
   334 		TPtrC fileName(NULL,0);
       
   335 
       
   336 		// If there is no filename present (legacy PRT based protocols) then we expect instead the uid of a
       
   337 		// three plane comms based flow factory that can can return a protocol description
       
   338 		if(ini->FindVar(protTag, KFilenameItemName, fileName) == EFalse)
       
   339 			{
       
   340 			// Deal with the flow case
       
   341 			// Fetch the UID of the flow factory
       
   342 			TInt flowFactoryUid;
       
   343 			if(ini->FindVar(protTag, KFlowFactoryUid, flowFactoryUid) == EFalse)
       
   344 				{
       
   345 #if defined(_DEBUG)
       
   346 				LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing 3PC based protocol - no flow factory UID found")));
       
   347 				Panic(EBadProtocolDescription);
       
   348 #else
       
   349 				User::Leave(KErrNotFound);
       
   350 #endif
       
   351 				}
       
   352 
       
   353 			// We need the flow factory container in order to instantiate a flow factory with ECOM
       
   354 			// Misconfiguration should not kill off c32 in a release build so we simply leave rather than panic
       
   355 #if defined(_DEBUG)
       
   356 			if(globals->iSubConnectionFlowFactories == NULL)
       
   357 				{
       
   358 				LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk files - flow factories not yet initialised")));
       
   359 				Panic(EBadProtocolDescription);
       
   360 				}
       
   361 #else
       
   362 			User::LeaveIfNull(globals->iSubConnectionFlowFactories);
       
   363 #endif
       
   364 
       
   365 			// Fetch the given factory and fetch the protocol description from it
       
   366 			CSubConnectionFlowFactoryBase* flowFactory =
       
   367 				static_cast<CSubConnectionFlowFactoryBase*>(globals->iSubConnectionFlowFactories->FindOrCreateFactoryL(TUid::Uid(flowFactoryUid)));
       
   368 			CleanupStack::PushL(flowFactory);
       
   369 
       
   370 			// Fetch the id of the protocol itself (as one factory can create flows of more than one type)
       
   371 			TInt protocol;
       
   372 			if(ini->FindVar(protTag, KFlowProtocol, protocol) == EFalse)
       
   373 				{
       
   374 				LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - no 3PC protocol found")));
       
   375 				__ASSERT_DEBUG(0, Panic(EBadProtocolDescription));
       
   376 				User::Leave(KErrNotFound);
       
   377 				}
       
   378 
       
   379 			// Ask for a protocol description from the flow factory and add that description to our globals
       
   380 #if defined(_DEBUG)
       
   381 			TServerProtocolDesc* protocolDescription = NULL;
       
   382 			TRAPD(descriptionError, protocolDescription = flowFactory->CreateFlowDescriptionL(protocol););
       
   383 			if(descriptionError != KErrNone)
       
   384 				{
       
   385 				LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - no protocol description provided by factory for 3PC based flow type")));
       
   386 				Panic(EBadProtocolDescription);
       
   387 				}
       
   388 #else
       
   389 			TServerProtocolDesc* protocolDescription = flowFactory->CreateFlowDescriptionL(protocol);
       
   390 #endif
       
   391 
       
   392 			CleanupStack::PushL(protocolDescription);
       
   393 			CProtocolRef::MakeRefL(protTag, protocolDescription);
       
   394 			globals->iNumProtocols++;
       
   395 			delete protocolDescription;
       
   396 
       
   397 			CleanupStack::Pop(2, flowFactory);
       
   398 			}
       
   399 		else
       
   400 			{
       
   401 			// Deal with the legacy case
       
   402 			TPtrC bindfrom(NULL, 0);
       
   403 			if (ini->FindVar(protTag,KBindFromItemName,bindfrom))
       
   404 				{
       
   405 				AddDependencyL(bindfrom, protTag);
       
   406 				}
       
   407 
       
   408 			CProtocolFamilyRef* protFamily = NULL;
       
   409 			TInt err;
       
   410 			TRAP(err, protFamily = CProtocolFamilyRef::GetProtocolFamilyL(fileName));
       
   411 			if (err != KErrNone)
       
   412 				{
       
   413 				continue;
       
   414 				}
       
   415 			CleanupStack::PushL(protFamily);
       
   416 
       
   417 			// Query the protocol family about all the socket types it can produce
       
   418 			// We'll remember them because we unload the libraries until we actually need them.
       
   419 			TServerProtocolDesc *protocolList = NULL;
       
   420 
       
   421 
       
   422 			// Note: some protocols will leave in their ProtocolList() method.  This
       
   423 			// is handled correctly here, although the naming convention is incorrect.
       
   424 			TInt numProtocols = 0;
       
   425 			TRAP(err, numProtocols = protFamily->ProtocolFamilyL(EFalse).ProtocolList(protocolList));
       
   426 
       
   427 			if (numProtocols == 0 || err != KErrNone)
       
   428 				{
       
   429 				LOG( ESockLog::Printf(_L("ProtocolManager: Protocol %S failed to load (error = %d, number of protocols = %d)"),
       
   430 					&protTag, err, numProtocols) );
       
   431 				CleanupStack::Pop(protFamily);
       
   432 				continue;
       
   433 				}
       
   434 
       
   435 #if defined (_DEBUG)
       
   436 			CheckProtocolList(protocolList,numProtocols);
       
   437 #endif
       
   438 			CleanupArrayDeletePushL(protocolList);
       
   439 			TInt num=0;
       
   440 			if (numProtocols>1)
       
   441 				{
       
   442 				if (ini->FindVar(protTag,KIndexTagName,num) == EFalse)
       
   443 					{
       
   444                     LOG(ESockLog::Printf(_L("ProtocolManager: error while parsing esk file - Protocol index missing")));
       
   445 					User::Leave(KErrNotFound);
       
   446 					}
       
   447 				num--;
       
   448 				}
       
   449 
       
   450 			if (num>numProtocols)
       
   451 				{
       
   452 				CleanupStack::Pop(protocolList);
       
   453 				CleanupStack::Pop(protFamily);
       
   454 				continue;
       
   455 				}
       
   456 
       
   457 
       
   458 			CProtocolRef *pp=CProtocolRef::MakeRefL(protTag,protFamily,protocolList+num);
       
   459 			if (pp==NULL)
       
   460 				{
       
   461 				User::Leave(KErrNoMemory);
       
   462 				}
       
   463 			CleanupStack::Pop(protocolList);
       
   464 			LOG(ESockLog::Printf(KESockSessDetailTag, _L("ProtocolManager: prot '%S' ref=%08x, famRef=%08x, num=%d"), &protTag, pp, protFamily, num));
       
   465 
       
   466 			globals->iNumProtocols++;
       
   467 
       
   468 			delete []protocolList;
       
   469 			CleanupStack::Pop(protFamily);
       
   470 			}
       
   471 		}
       
   472 	while (ch!=0);	// ch==0 when last token removed from TLex
       
   473 
       
   474 	// Leave if there's no point in carrying on. - i.e. no protocols.
       
   475 	if (globals->iNumProtocols==0)
       
   476 		{
       
   477 		LOG(ESockLog::Printf(_L("ProtocolManager: No protocols - leaving.")));
       
   478 		User::Leave(KErrBadDriver);
       
   479 		}
       
   480 
       
   481 	// Delete all protocolfamilybase objects, causing DLLs to unload
       
   482 	LOG(ESockLog::Printf(_L("ProtocolManager: Finished initialising. Unloading all PRTs.")));
       
   483 	TSglQueIter<CProtocolFamilyRef> familyIter(*globals->iProtocolFamilies);
       
   484 	CProtocolFamilyRef* family;
       
   485 	while(family=familyIter++,family!=NULL)
       
   486 		{
       
   487 		delete &(family->ProtocolFamilyL(EFalse));
       
   488 		}
       
   489 
       
   490 	LOG(ESockLog::Printf(_L("ProtocolManager: Done.")));
       
   491 
       
   492 	if(globals->iDeps)
       
   493 		{
       
   494 		LOG(ESockLog::Printf(_L("Dependencies: %S"), &*(globals->iDeps)));
       
   495 		}
       
   496 	}
       
   497 
       
   498 void ProtocolManager::SafeCleanupProtocol(TAny* aProtocolRef)
       
   499 /**
       
   500 Try to clean up a protocol instance
       
   501 
       
   502 This routine is pushed onto the cleanup stack in order to clean up a protocol instance.
       
   503 The check against the protocol pointer being non-NULL is a safety check.  This routine was
       
   504 created because ProtocolManager::CleanupProtocol(protocol) was being called in circumstances
       
   505 where the protocol had already gone and the pointer to it had become invalid.  This routine
       
   506 takes as argument a pointer to the CProtocolRef instance of the protocol, so that the protocol
       
   507 pointer can be checked against NULL.
       
   508 
       
   509 @param aProtocolRef pointer to the CProtocolRef instance whose protocol needs to be deleted
       
   510 */
       
   511 	{
       
   512 	CProtocolRef *pRef = reinterpret_cast<CProtocolRef*>(aProtocolRef);
       
   513 	if (pRef->Protocol())
       
   514 		{
       
   515 		pRef->Protocol()->TryDelete();
       
   516 		}
       
   517 	}
       
   518 
       
   519 void ProtocolManager::CleanupProtocol(TAny* aProtocol)
       
   520 	{
       
   521 	((CProtocolBase *)aProtocol)->TryDelete();
       
   522 	}
       
   523 
       
   524 void ProtocolManager::TransferSocketL(CSocket* aSocket, CPlayer* aPlayer)
       
   525 /**
       
   526 Transfer socket from one session to another
       
   527 */
       
   528 	{
       
   529 
       
   530 	//-- check the flag that enables socket transfer and the capabilities of the process that owns aSession,
       
   531 	//-- where the socket is supposed to be transferred.
       
   532 	if(aSocket->iSecTransferEnabled && aSocket->iTransferSecPolicy.CheckPolicy(aPlayer->SafeMessage()))
       
   533 	    {//-- everything is OK, reset socket transfer flag.
       
   534 	    aSocket->iSecTransferEnabled = EFalse;
       
   535 	    }
       
   536 	else
       
   537 	    {//-- security check failed.
       
   538 	    User::Leave(KErrPermissionDenied);
       
   539         }
       
   540 
       
   541 	if (aSocket->iSSP)
       
   542 	    {
       
   543  		// For non-null sockets, ask the socket provider to perform security
       
   544  		// policy checking on new session
       
   545  		User::LeaveIfError(aSocket->iSSP->SecurityCheck(aPlayer->CurrentSession()));
       
   546  		}
       
   547 
       
   548 	// Add the protocol of the socket being transferred to the receipient session's list of protocols
       
   549 	// The socket doesn't know about legacy protocols directly anymore so we need to find the protocol
       
   550 	TProtocolDesc* info = aSocket->iProtocolInfo;
       
   551 	__ASSERT_DEBUG(info, User::Panic(KSpecAssert_ESockSSockS_MAN, 1));
       
   552 	CProtocolRef* protocolReference = FindProtocolL(info->iAddrFamily, info->iSockType, info->iProtocol);
       
   553 	CProtocolBase* protocol = protocolReference->Protocol();
       
   554 
       
   555 	// The protocol reference will not have a protocol member if it refers to a new 3PC based flow
       
   556 	// Add the protocol to the sessionproxy for the session receiving the socket
       
   557 	if(protocol)
       
   558 		{
       
   559 		aPlayer->CurrentSessionProxyL()->AddProtocolL(protocol);
       
   560 		}
       
   561 	}
       
   562 
       
   563 CProtocolBase* ProtocolManager::FindAndLoadProtocolL(const TDesC& aName, TProtocolType aType)
       
   564 /**
       
   565 Find a protocol by name and load it.
       
   566 Caller is responsible for ultimately deleting the protocol
       
   567 
       
   568 This is for use by extension DLLs as it does not attach the protocol
       
   569 to a session.
       
   570 
       
   571 */
       
   572 	{
       
   573 	TServerProtocolDesc pinfo;
       
   574 	User::LeaveIfError(ProtocolInfo(aName,pinfo));
       
   575 	switch (aType)
       
   576 		{
       
   577 	case ENormalProtocol:
       
   578 		// Dont care what extra interfaces it supports
       
   579 		break;
       
   580 	case EInterfaceProtocol:
       
   581 		// Need a protocol that support Interface extensions
       
   582 		if (!(pinfo.iServiceTypeInfo & EInterface))
       
   583 			{
       
   584 			User::Leave(KErrBadName);
       
   585 			}
       
   586 		break;
       
   587 		}
       
   588 	return (FindAndLoadProtocolL(pinfo.iAddrFamily, pinfo.iSockType, pinfo.iProtocol));
       
   589 	}
       
   590 
       
   591 CProtocolBase* ProtocolManager::FindAndLoadProtocolL(TUint aAddrFamily,TUint aSockType,TUint aProtocol)
       
   592 /**
       
   593 Find a protocol by address family, socket type, and protocol ID and load it.
       
   594 Caller is responsible for ultimately deleting the protocol
       
   595 
       
   596 This is for use by extension DLLs as it does not attach the protocol
       
   597 to a session.
       
   598 */
       
   599 	{
       
   600 	CProtocolRef* pref = FindProtocolL(aAddrFamily,aSockType,aProtocol);
       
   601 	pref->LoadAndBindL();
       
   602 	return pref->Protocol();
       
   603 	}
       
   604 
       
   605 void ProtocolManager::LoadProtocolL(TUint anAddrFamily, TUint aSocketType, TUint aProtocol, CPlayer* aPlayer)
       
   606 /**
       
   607 Manually load the specified protocol
       
   608 This is used by clients who need to ensure that an open call will not take a
       
   609 significant amount of time (e.g. IrCOMM) It effectively makes all the lengthy parts of Open asynchronous.
       
   610 
       
   611 */
       
   612     {
       
   613 	CProtocolRef* prot = FindProtocolL(anAddrFamily, aSocketType, aProtocol);
       
   614 
       
   615 	// If the protocol reference is for a "three plane comms" based flow then we silently return
       
   616 	// without loading anything as their lifetime is managed by ECOM and therefore explicit loading is not supported
       
   617 	if(prot->GetFlag() & CProtocolRef::EThreePlaneCommsBased)
       
   618 	    {
       
   619 		return;
       
   620 	    }
       
   621 
       
   622 	// Got one, make sure the library is loaded and we have an instance of the protocol object.
       
   623 	prot->LoadAndBindL();
       
   624 	CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
       
   625 
       
   626 	// register the  protocol with the Session
       
   627 	aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
       
   628 	CleanupStack::Pop();
       
   629 	}
       
   630 
       
   631 void ProtocolManager::UnLoadProtocolL(TUint anAddrFamily, TUint aSocketType, TUint aProtocol, CPlayer* aPlayer)
       
   632 /**
       
   633 Do the opposite of the above function
       
   634 
       
   635 */
       
   636     {
       
   637     CProtocolRef* prot = FindProtocolL(anAddrFamily, aSocketType, aProtocol);
       
   638 
       
   639 	// If the protocol reference is for a "three plane comms" based flow then we silently return
       
   640 	// without attempting to unload anything as their lifetime is managed by ECOM only
       
   641 	if(prot->GetFlag() & CProtocolRef::EThreePlaneCommsBased)
       
   642 	    {
       
   643 		return;
       
   644 	    }
       
   645 
       
   646     aPlayer->CurrentSessionProxyL()->RemoveProtocolL(prot->Protocol());
       
   647     }
       
   648 
       
   649 CHostResolver* ProtocolManager::NewHostResolverL(TUint anAddrFamily, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   650 /**
       
   651 Create a new host resolver object
       
   652 
       
   653 */
       
   654 	{
       
   655 	CProtocolRef * prot=FindProtocolL(anAddrFamily,KUndefinedSockType,aProtocolId);
       
   656 	if (!(prot->Info().iNamingServices & KNSNameResolution))
       
   657 	    {
       
   658 		User::Leave(KErrNotSupported);
       
   659 	    }
       
   660 
       
   661 	// Got one, make sure protocol & library are loaded
       
   662 	prot->LoadAndBindL();
       
   663 
       
   664 	CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
       
   665 
       
   666 	CHostResolvProvdBase* hr=prot->Protocol()->NewHostResolverL();
       
   667 
       
   668 	// Give the host resolver the info to clean up after itself.
       
   669 	hr->iProtocol=prot->Protocol();
       
   670 
       
   671     CleanupStack::Pop();
       
   672 	CleanupStack::PushL(hr);
       
   673 
       
   674 
       
   675 	// ask the resolver provider to perform security policy checking
       
   676 	User::LeaveIfError(hr->SecurityCheck(aPlayer->CurrentSession()));
       
   677 	CHostResolver* r=CHostResolver::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
       
   678 
       
   679 //	CleanupStack::PushL(r);
       
   680 
       
   681 
       
   682 //	CleanupStack::Pop(r);
       
   683 //	CleanupStack::PushL(TCleanupItem(CloseSubSession,r));
       
   684 
       
   685 	// register the  protocol with the Session
       
   686 //	aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
       
   687 
       
   688 	aPlayer->SubSessions().AppendL(r);
       
   689 	hr->SetNotify(r);
       
   690 	r->SetResolver(hr);
       
   691 	CleanupStack::Pop(r);
       
   692 	CleanupStack::Pop(hr);
       
   693 //	CleanupStack::Pop(1);
       
   694 
       
   695 	return r;
       
   696 	}
       
   697 
       
   698 CServiceResolver* ProtocolManager::NewServiceResolverL(TUint anAddrFamily, TUint aSocketType, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   699 /**
       
   700 Create a new service resolver provider
       
   701 
       
   702 */
       
   703 	{
       
   704 	CProtocolRef * prot=FindProtocolL(anAddrFamily,aSocketType,aProtocolId);
       
   705 	if (!(prot->Info().iNamingServices & KNSServiceResolution))
       
   706 	    {
       
   707 		User::Leave(KErrNotSupported);
       
   708 	    }
       
   709 
       
   710 	// Got one, make sure protocol & library are loaded
       
   711 	prot->LoadAndBindL();
       
   712 	CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
       
   713 
       
   714 	CServiceResolvProvdBase *sr=NULL;
       
   715 
       
   716 	sr=prot->Protocol()->NewServiceResolverL();
       
   717 	CleanupStack::PushL(sr);
       
   718 
       
   719 	// Give the host resolver the info to clean up after itself.
       
   720 	sr->iProtocol=prot->Protocol();
       
   721 
       
   722 	// ask the resolver provider to perform security policy checking
       
   723 	User::LeaveIfError(sr->SecurityCheck(aPlayer->CurrentSession()));
       
   724 	CServiceResolver* s=CServiceResolver::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
       
   725 	sr->SetNotify(s);
       
   726 
       
   727 //	CleanupStack::PushL(TCleanupItem(CloseSubSession,s));
       
   728 
       
   729 	// register the  protocol with the Session
       
   730 //	aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
       
   731 
       
   732 	aPlayer->SubSessions().AppendL(s);
       
   733 	s->SetResolver(sr);
       
   734 
       
   735 	CleanupStack::Pop(3);
       
   736 	return s;
       
   737 	}
       
   738 
       
   739 CNetDatabase* ProtocolManager::NewNetDatabaseL(TUint anAddrFamily, TUint aProtocolId, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   740 /**
       
   741 Create a new database type thang
       
   742 
       
   743 */
       
   744 	{
       
   745 	CProtocolRef * prot=FindProtocolL(anAddrFamily,KUndefinedSockType,aProtocolId);
       
   746 	if (!(prot->Info().iNamingServices & KNSInfoDatabase))
       
   747 		{
       
   748 		User::Leave(KErrNotSupported);
       
   749 		}
       
   750 
       
   751 	// Got one, make sure protocol & library are loaded
       
   752 	prot->LoadAndBindL();
       
   753 	CleanupStack::PushL(TCleanupItem(ProtocolManager::CleanupProtocol,prot->Protocol()));
       
   754 
       
   755 	CNetDBProvdBase *db=NULL;
       
   756 	db=prot->Protocol()->NewNetDatabaseL();
       
   757 
       
   758 	CleanupStack::PushL(db);
       
   759 
       
   760 	// Give the host resolver the info to clean up after itself.
       
   761 	db->iProtocol=prot->Protocol();
       
   762 
       
   763 	// ask the net database provider to perform security policy checking
       
   764 	User::LeaveIfError(db->SecurityCheck(aPlayer->CurrentSession()));
       
   765 
       
   766 	CNetDatabase* n=CNetDatabase::NewLC(prot, aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId);
       
   767 	db->SetNotify(n);
       
   768 //	CleanupStack::Pop();
       
   769 
       
   770 //	CleanupStack::PushL(TCleanupItem(CloseSubSession,n));
       
   771 
       
   772 	// register the  protocol with the Session
       
   773 //	aPlayer->CurrentSessionProxyL()->AddProtocolL(prot->Protocol());
       
   774 
       
   775 	aPlayer->SubSessions().AppendL(n);
       
   776 	n->SetProvd(db);
       
   777 
       
   778 	CleanupStack::Pop(3);
       
   779 	return n;
       
   780 	}
       
   781 
       
   782 CInternalSocketImpl* ProtocolManager::NewInternalSocketL ( TAny* aParams, const TDesC& aName )
       
   783 	{
       
   784 	TServerProtocolDesc pinfo;
       
   785 	User::LeaveIfError(ProtocolInfo(aName,pinfo));
       
   786 	return ProtocolManager::NewInternalSocketL ( aParams, pinfo.iAddrFamily, pinfo.iSockType, pinfo.iProtocol );
       
   787 	}
       
   788 
       
   789 CInternalSocketImpl* ProtocolManager::NewInternalSocketL ( TAny* aParams, TUint aAddrFamily, TUint aSockType, TUint aProtocol )
       
   790 	{
       
   791 	CInternalSockSubSession::TParameters* params = reinterpret_cast < CInternalSockSubSession::TParameters* > ( aParams );
       
   792 	CProtocolRef* prot = FindProtocolL ( aAddrFamily, aSockType, aProtocol );
       
   793 	if (!(prot->Info().iServiceTypeInfo&ESocketSupport))
       
   794 	    {
       
   795 		User::Leave(KErrNotSupported);
       
   796 		}
       
   797 	prot->LoadAndBindL ();
       
   798 	// Please check @NewSocketL to see why we need to push this item.
       
   799 	CleanupStack::PushL ( TCleanupItem ( ProtocolManager::CleanupProtocol,prot->Protocol () ) );
       
   800 	CInternalSocketImpl* intSock = CInternalSocketImpl::NewL ( *params, &( prot->Info() ), prot->Protocol() );
       
   801 	CleanupStack::Pop (); // prot
       
   802 	return intSock;
       
   803 	}
       
   804 
       
   805 TUint ProtocolManager::NumProtocols(void)
       
   806 	{
       
   807 
       
   808 	return SockManGlobals::Get()->iNumProtocols;
       
   809 	}
       
   810 
       
   811 TInt ProtocolManager::ProtocolInfo(const TDesC &aName,TProtocolDesc &aProtocol)
       
   812 	{
       
   813 	TInt ret;
       
   814 	TServerProtocolDesc info;
       
   815 
       
   816 	ret = ProtocolInfo(aName, info);
       
   817 	if (ret==KErrNone)
       
   818 		{
       
   819 		aProtocol = info;
       
   820 		}
       
   821 	return ret;
       
   822 	}
       
   823 
       
   824 
       
   825 TInt ProtocolManager::ProtocolInfo(const TDesC &aName,TServerProtocolDesc &aProtocol)
       
   826 /**
       
   827 Find a protocol by name - no wildcard support.
       
   828 
       
   829 */
       
   830 	{
       
   831 	TSglQueIter<CProtocolRef> i(*SockManGlobals::Get()->iProtocols);
       
   832 
       
   833 	// Run the queue looking for a match.
       
   834 	do
       
   835 		{
       
   836 		if(((CProtocolRef *)i)->Info().iName.Compare(aName)==0)
       
   837 			{
       
   838 			aProtocol=((CProtocolRef*)i)->Info();
       
   839 			return KErrNone;
       
   840 			}
       
   841 		i++;
       
   842 		}
       
   843 	while((CProtocolRef *)i);
       
   844 
       
   845 	return KErrNotFound;
       
   846 	}
       
   847 
       
   848 
       
   849 CProtocolRef* ProtocolManager::FindProtocolL(TInt anAddrFamily,TUint aSocketType,TInt aProtocol)
       
   850 /**
       
   851  Find a protocol from the lists.
       
   852 */
       
   853 	{
       
   854 
       
   855 	TSglQueIter<CProtocolRef> i(*SockManGlobals::Get()->iProtocols);
       
   856 
       
   857 	CProtocolRef *pP;
       
   858 	// Run the protocol queue looking for a match on requested socket type.
       
   859 	while ((pP=i++)!=NULL)
       
   860 		{
       
   861 		if (pP->Matches(anAddrFamily,aSocketType,aProtocol))
       
   862 			{
       
   863 			return pP;
       
   864 			}
       
   865 		}
       
   866 
       
   867 	User::Leave(KErrBadName);
       
   868 	return NULL;	//lint !e527	// LINT knows we can't get here
       
   869 	}
       
   870 
       
   871 
       
   872 CProtocolFamilyRef::CProtocolFamilyRef()
       
   873 	:CBase()
       
   874 	{
       
   875 	}
       
   876 
       
   877 CProtocolFamilyRef::~CProtocolFamilyRef()
       
   878 	{
       
   879 	if (iLibFileName)
       
   880 		{
       
   881 		delete iLibFileName;
       
   882 		}
       
   883 	}
       
   884 
       
   885 CProtocolFamilyRef* CProtocolFamilyRef::GetProtocolFamilyL(TDesC& aName)
       
   886 /**
       
   887 Either return a pointer to an existing protocol ref or create a new one.
       
   888 
       
   889 */
       
   890 	{
       
   891 
       
   892 	TSglQue<CProtocolFamilyRef>* families=SockManGlobals::Get()->iProtocolFamilies;
       
   893 	TSglQueIter<CProtocolFamilyRef> i(*families);
       
   894 
       
   895 	// Run through the list of existing protocols looking for a match.
       
   896 	CProtocolFamilyRef* protRef;
       
   897 	while(protRef=(CProtocolFamilyRef *)i,protRef)
       
   898 		{
       
   899 		if(protRef->iLibFileName->Compare(aName)==0)
       
   900 			{
       
   901 			if (protRef->iProtocolFamily)
       
   902 				{
       
   903 				return protRef;
       
   904 				}
       
   905 			else
       
   906 				{
       
   907 				break;
       
   908 				}
       
   909 			}
       
   910 		i++;
       
   911 		}
       
   912 
       
   913 	// Not found one yet - we must create one.
       
   914 	if (!protRef)
       
   915 		{
       
   916 		protRef=new(ELeave) CProtocolFamilyRef;
       
   917 		CleanupStack::PushL(protRef);
       
   918 		protRef->iLibFileName=aName.AllocL();
       
   919 
       
   920       // Ensure that this protocol we're about to return is loaded
       
   921       protRef->LoadL();
       
   922 
       
   923       // If it didn't leave, then add it to the list
       
   924       families->AddLast(*protRef);
       
   925 		}
       
   926 	else
       
   927 		{
       
   928 		CleanupStack::PushL(protRef);
       
   929       // Ensure that this protocol we're about to return is loaded
       
   930       protRef->LoadL();
       
   931 		}
       
   932 
       
   933 	CleanupStack::Pop();
       
   934 
       
   935 	return protRef;
       
   936 	}
       
   937 
       
   938 void CProtocolFamilyRef::LoadL()
       
   939 /**
       
   940 Load the protocol. Leave it un-initted until the last minute - i.e. init it in the accessor.
       
   941 
       
   942 */
       
   943 	{
       
   944 	if (iProtocolFamily)
       
   945 		{
       
   946 		return;
       
   947 		}
       
   948 
       
   949 	TAutoClose<RLibrary> lib;
       
   950 	const TInt ret = lib.iObj.Load(*iLibFileName);
       
   951 	LOG(TBuf8<64> buf8);
       
   952 	LOG(buf8.Copy(iLibFileName->Des()));
       
   953 	LOG(ESockLog::Printf(KESockProvChoresTag, _L8("CProtocolFamilyRef(%08x)::LoadL '%S' [ret=%d]"), this, &buf8, ret));
       
   954 	if(ret!=KErrNone)
       
   955 		{
       
   956 		delete iLibFileName; // cleanup after aName.AllocL
       
   957 		iLibFileName = NULL;
       
   958 		User::Leave(ret);
       
   959 		}
       
   960 	lib.PushL();
       
   961 
       
   962 	// The Uid check
       
   963 #ifdef _UNICODE
       
   964 	if(lib.iObj.Type()[1]!=TUid::Uid(KUidUnicodeProtocolModule))
       
   965 		{
       
   966 		LOG(ESockLog::Printf(_L8("FAILED uid check! (type=%08X)"), lib.iObj.Type()[1].iUid));
       
   967 		User::Leave(KErrBadLibraryEntryPoint);
       
   968 		}
       
   969 #else
       
   970 	if(lib.iObj.Type()[1]!=TUid::Uid(KUidProtocolModule))
       
   971 		{
       
   972 		User::Leave(KErrBadLibraryEntryPoint);
       
   973 		}
       
   974 #endif
       
   975 
       
   976 	TProtocolNew libEntry=(TProtocolNew)lib.iObj.Lookup(1);
       
   977 	if (libEntry==NULL)
       
   978 		{
       
   979 		LOG(ESockLog::Printf(_L8("FAILED retrieving factory entrypoint (ord 1)")));
       
   980 		User::Leave(KErrNoMemory);
       
   981 		}
       
   982 
       
   983 	iProtocolFamily=(*libEntry)();
       
   984 	if (!iProtocolFamily)
       
   985 		{
       
   986 		LOG(ESockLog::Printf(_L8("FAILED running factory entrypoint")));
       
   987 		User::Leave(KErrNoMemory);
       
   988 		}
       
   989 
       
   990 	//	Make sure the protocol family has all the info needed to clean up after itself.
       
   991 	iProtocolFamily->iManagerRef=this;
       
   992 	TRAPD(res, iProtocolFamily->SetLibraryL(lib.iObj));
       
   993 	if(res != KErrNone)
       
   994 		{
       
   995 		LOG(ESockLog::Printf(_L8("FAILED creating lib unloader (err %d)"), res));
       
   996 		delete iProtocolFamily;
       
   997 		iProtocolFamily=0;
       
   998 		User::Leave(res);
       
   999 		}
       
  1000 
       
  1001 	lib.Pop();
       
  1002 	lib.iObj.SetHandle(0); // Dont let ~TAutoClose() close library
       
  1003 	}
       
  1004 
       
  1005 CProtocolFamilyBase& CProtocolFamilyRef::ProtocolFamilyL(TBool aInstall)
       
  1006 /**
       
  1007 Accessor to ProtocolFamily from manager ref - this must leave because we perform late loading and
       
  1008 hence must allocate memory and other nasty grubby things.
       
  1009 
       
  1010 */
       
  1011 	{
       
  1012 	if (!iProtocolFamily)
       
  1013 		{
       
  1014 		LoadL();
       
  1015 		}
       
  1016 	__ASSERT_DEBUG(iProtocolFamily, User::Panic(KSpecAssert_ESockSSockS_MAN, 2));
       
  1017 
       
  1018 	if (aInstall && !(iFlags&EInstalled))
       
  1019 		{
       
  1020 		TInt r=iProtocolFamily->Install();
       
  1021 		if (r!=KErrNone)
       
  1022 			{
       
  1023 			delete iProtocolFamily;
       
  1024 			iProtocolFamily=0;
       
  1025 			User::Leave(r);
       
  1026 			}
       
  1027 		iFlags|=EInstalled;
       
  1028 		}
       
  1029 
       
  1030 	return *iProtocolFamily;
       
  1031 	}
       
  1032 
       
  1033 CProtocolRef::~CProtocolRef()
       
  1034 	{
       
  1035 	delete iTag;
       
  1036 	}
       
  1037 
       
  1038 CProtocolRef::CProtocolRef()
       
  1039 	:CBase()
       
  1040 	{
       
  1041 	}
       
  1042 
       
  1043 TBool CProtocolRef::Matches(TUint anAddrFamily,TUint aSockType,TUint aProtocol)
       
  1044 /**
       
  1045 Return ETrue if a protocol desc matches the specified family type and protocol
       
  1046 We allow clients to be a little hazy about their exact requirements
       
  1047 
       
  1048 */
       
  1049 	{
       
  1050 	if(iInfo.iAddrFamily==anAddrFamily &&
       
  1051 		(iInfo.iSockType==KUndefinedSockType || aSockType==KUndefinedSockType || iInfo.iSockType==aSockType) &&
       
  1052 		(iInfo.iProtocol==KUndefinedProtocol || aProtocol==KUndefinedProtocol || iInfo.iProtocol==aProtocol))
       
  1053 		{
       
  1054 		return ETrue;
       
  1055 		}
       
  1056 	else
       
  1057 		{
       
  1058 		return EFalse;
       
  1059 		}
       
  1060 	}
       
  1061 
       
  1062 
       
  1063 CProtocolRef* CProtocolRef::GetProtocolNoCreate(TProtocolRefList *iProtocolList, const TDesC& aTag)
       
  1064 /**
       
  1065 Find a protocol from the lists by name
       
  1066 Return null if not found;
       
  1067 */
       
  1068 	{
       
  1069 	TSglQueIter<CProtocolRef> i(*iProtocolList);
       
  1070 
       
  1071 	CProtocolRef *pP = NULL;
       
  1072 	// Run the protocol queue looking for a match on requested name
       
  1073 	while ((pP=i++)!=NULL)
       
  1074 		{
       
  1075 		if (pP->iTag->Compare(aTag)==0)
       
  1076 			{
       
  1077 			return pP;
       
  1078 			}
       
  1079 		}
       
  1080 	return NULL;
       
  1081 	}
       
  1082 
       
  1083 CProtocolRef* CProtocolRef::GetProtocolL(const TDesC& aTag)
       
  1084 /**
       
  1085 Find a protocol from the lists by name
       
  1086 Will make a new ref and families if required.
       
  1087 
       
  1088 */
       
  1089 	{
       
  1090 	TSglQue<CProtocolRef>* protocols=SockManGlobals::Get()->iProtocols;
       
  1091 
       
  1092 
       
  1093 	CProtocolRef *pP = GetProtocolNoCreate(protocols,aTag);
       
  1094 
       
  1095 	if (!pP)
       
  1096 		{
       
  1097 		pP=MakeRefL(aTag);
       
  1098 		}
       
  1099 
       
  1100 	return pP;
       
  1101 	}
       
  1102 
       
  1103 void CProtocolRef::Cleanup(TAny* aFamily)
       
  1104 /**
       
  1105 Close a protocol family from the cleanup stack.
       
  1106 
       
  1107 */
       
  1108 	{
       
  1109 	((CProtocolFamilyRef *)aFamily)->Close();
       
  1110 	}
       
  1111 
       
  1112 void CloseProtocol(TAny* aProtocol)
       
  1113     {
       
  1114      ((CProtocolBase*)aProtocol)->Close();
       
  1115     }
       
  1116 void BindingLeave(TAny* aProtRef)
       
  1117  	{
       
  1118  	TUint flag=((CProtocolRef*)aProtRef)->GetFlag();
       
  1119  	((CProtocolRef*)aProtRef)->SetFlag(~(CProtocolRef::EBound) & flag);
       
  1120  	}
       
  1121 
       
  1122 void CProtocolRef::LoadL(TBool aLoadForBinding)
       
  1123 /**
       
  1124 Fill in a protocol ref - loading any libs or families
       
  1125 Loads and binds the requested protocol loading any libraries required.
       
  1126 May go recursive if a bindee needs loading and the aloadForBinding argument is set.
       
  1127 
       
  1128 */
       
  1129 	{
       
  1130 	if (iProtocol)
       
  1131  		{
       
  1132  		if (!aLoadForBinding)
       
  1133  			{
       
  1134  			CleanupStack::PushL(TCleanupItem(BindingLeave, this));
       
  1135  			ResolveBindingL();
       
  1136  			CleanupStack::Pop();
       
  1137  			}
       
  1138    		return;
       
  1139  		}
       
  1140 
       
  1141 	// Three plane comms protos shouldn't be loading like this
       
  1142 	__ASSERT_DEBUG(! (GetFlag() & CProtocolRef::EThreePlaneCommsBased), User::Panic(KSpecAssert_ESockSSockS_MAN, 3));
       
  1143 	
       
  1144 	__ASSERT_DEBUG(iFamily, User::Panic(KSpecAssert_ESockSSockS_MAN, 4));
       
  1145 	iFamily->ProtocolFamilyL().Open();
       
  1146 
       
  1147 	CleanupStack::PushL(TCleanupItem(CProtocolRef::Cleanup,iFamily));
       
  1148 
       
  1149 	// Get the Protocol from the family
       
  1150 	iProtocol=iFamily->ProtocolFamilyL().NewProtocolL(iInfo.iSockType,iInfo.iProtocol);
       
  1151 
       
  1152 	// At this stage the iProtocol member effectively takes over control of closing
       
  1153 	// the family reference
       
  1154 	// Note there is a work around in TCPIP 047 which fixes the problem
       
  1155 	// by pushing a NULL reference
       
  1156 	CleanupStack::Pop();
       
  1157 
       
  1158 	//	Make sure the protocol has the info needed to clean up after itself.
       
  1159 	iProtocol->iManagerRef=this;
       
  1160 
       
  1161 	CleanupStack::PushL(iProtocol);
       
  1162 	if (!(iFlags & EInited))
       
  1163 		{
       
  1164 		iProtocol->InitL(*iTag);
       
  1165 		iFlags|=EInited;
       
  1166 		}
       
  1167 
       
  1168 	if (!aLoadForBinding)
       
  1169 		{
       
  1170 		ResolveBindingL();
       
  1171 		}
       
  1172 
       
  1173 	CleanupStack::Pop(1);  // Was pop(2) see comment above
       
  1174 	}
       
  1175 
       
  1176 void CProtocolRef::ResolveBindingL()
       
  1177 /**
       
  1178 Resolve binding requirements for a top level (i.e service provider) protocol
       
  1179 
       
  1180 */
       
  1181 	{
       
  1182 	if (iFlags&EBound)
       
  1183 		{
       
  1184 		return;
       
  1185 		}
       
  1186 
       
  1187 	LoadL(ETrue);
       
  1188 //	CESockIniData* ini=CESockIniData::NewL();
       
  1189 //	CleanupStack::PushL(ini);
       
  1190 
       
  1191 	const CESockIniData* ini=SockManGlobals::Get()->IniData();
       
  1192 	DoBindingL(*ini);
       
  1193 //	CleanupStack::PopAndDestroy(ini);
       
  1194 
       
  1195 	iFlags|=EBound;
       
  1196 	}
       
  1197 
       
  1198 
       
  1199 void CProtocolRef::DoBindingL(const CESockIniData& aIniFile)
       
  1200 /**
       
  1201  Actually perform the binding for a given protocol. Recursive
       
  1202 */
       
  1203 	{
       
  1204 	if (iFlags&EBound)
       
  1205 		{
       
  1206 		return;
       
  1207 		}
       
  1208 
       
  1209 	iFlags|=EBound;	// Set "is bound" flag here to preempt any recursive binding.
       
  1210 
       
  1211 	TPtrC bindList;
       
  1212 	if (aIniFile.FindVar(*iTag,KBindToItemName,bindList))
       
  1213 		{
       
  1214 		// BindTo scenario. Proceed with the node current node is binding to
       
  1215 		ProcessBindListL(bindList, aIniFile);
       
  1216 		}
       
  1217 
       
  1218 	TPtrC depList;
       
  1219 	TBool foundDep = ProtocolManager::GetDependency(*iTag,depList);
       
  1220 	if(foundDep)
       
  1221 		{
       
  1222 		// BindFrom scenario. Proceed with the node that is binding from to current one
       
  1223 		ProcessBindListL(depList, aIniFile);
       
  1224 		}
       
  1225 
       
  1226 	StartL();
       
  1227 	}
       
  1228 
       
  1229 void CProtocolRef::ProcessBindListL(TPtrC aBindList, const CESockIniData& aIniFile)
       
  1230 	{
       
  1231 	LOG( ESockLog::Printf(_L("ProcessBindListL(aBindList = %S)"), &aBindList) );
       
  1232 	TLex lex(aBindList);
       
  1233 	TChar ch=0;
       
  1234 	do
       
  1235 		{
       
  1236 		lex.Mark();
       
  1237 		do
       
  1238 			{
       
  1239 			ch=lex.Get();
       
  1240 			}
       
  1241 		while (ch!=',' && ch!=0);
       
  1242 
       
  1243 		if (ch==',')
       
  1244 			{
       
  1245 			lex.UnGet();
       
  1246 			}
       
  1247 
       
  1248 		CProtocolRef* prot=GetProtocolL(lex.MarkedToken());
       
  1249 		lex.Get();
       
  1250 		prot->LoadL(ETrue);
       
  1251 		prot->iProtocol->Open();
       
  1252 
       
  1253 		CleanupStack::PushL(TCleanupItem(CloseProtocol, prot->iProtocol));
       
  1254 		CleanupStack::PushL(TCleanupItem(BindingLeave, prot));
       
  1255 
       
  1256 		prot->DoBindingL(aIniFile);
       
  1257 		prot->StartL();
       
  1258 
       
  1259 		LOG_STMT(TPtrC bindFrom = iProtocol->Tag();)
       
  1260 		LOG_STMT(TPtrC bindTo = prot->iProtocol->Tag();)
       
  1261 		LOG( ESockLog::Printf(_L("ProcessBindListL(Binding: %S -> %S)"), &bindFrom, &bindTo) );
       
  1262 
       
  1263 		iProtocol->BindToL(prot->iProtocol);
       
  1264 
       
  1265 		CleanupStack::Pop();
       
  1266 		CleanupStack::PopAndDestroy();
       
  1267 		}
       
  1268 	while (ch!=0); // ch == 0 when last token extracted from TLex
       
  1269 	}
       
  1270 
       
  1271 
       
  1272 CProtocolRef* CProtocolRef::MakeRefL(const TDesC& aTag,CProtocolFamilyRef* aFamily,TServerProtocolDesc* anInfo)
       
  1273 /**
       
  1274 Protocol reference 'constructor'.
       
  1275 CProtocolRef really is a refernece and hence it runs the list of currently loaded protocols
       
  1276 before really and truly loading
       
  1277 
       
  1278 */
       
  1279 	{
       
  1280 	CProtocolRef* pP=new(ELeave) CProtocolRef;
       
  1281 	CleanupStack::PushL(pP);
       
  1282 	pP->iTag=aTag.AllocL();
       
  1283 
       
  1284 	if (aFamily==NULL && anInfo==NULL)
       
  1285 		{
       
  1286 		TPtrC familyName(NULL,0);
       
  1287 
       
  1288 		const CESockIniData* ini=SockManGlobals::Get()->IniData();
       
  1289 		if (!ini->FindVar(aTag,KFilenameItemName,familyName))
       
  1290 			{
       
  1291 			User::Leave(KErrBadName);
       
  1292 			}
       
  1293 		pP->iFamily=CProtocolFamilyRef::GetProtocolFamilyL(familyName);
       
  1294 
       
  1295 		TServerProtocolDesc* protocolList;
       
  1296 		TInt numProtocols=pP->iFamily->ProtocolFamilyL().ProtocolList(protocolList);
       
  1297 		TInt index=0;
       
  1298 
       
  1299 		if (numProtocols>1 && !ini->FindVar(aTag,KIndexTagName,index))
       
  1300 			{
       
  1301 			User::Leave(KErrBadName);
       
  1302 			}
       
  1303 
       
  1304 		pP->iInfo=protocolList[index-1];
       
  1305 		delete[] protocolList;
       
  1306 		}
       
  1307 	else
       
  1308 		{
       
  1309 		pP->iInfo=*anInfo;
       
  1310 		pP->iFamily=aFamily;
       
  1311 		}
       
  1312 
       
  1313 	TSglQue<CProtocolRef>* protList = SockManGlobals::Get()->iProtocols;
       
  1314 #ifdef _DEBUG
       
  1315 	CProtocolRef* ref = GetProtocolNoCreate(protList,aTag);
       
  1316 	if (ref) // uhoh we have a duplicate protocol better panic in debug mode
       
  1317 		{
       
  1318 		LOG( ESockLog::Printf(_L("ERROR in config - duplicate protocol loaded: %S loaded more than once"),&aTag));
       
  1319 		Panic(EBadProtocolDescription);
       
  1320 		}
       
  1321 #endif
       
  1322 	protList->AddLast(*pP);
       
  1323 	CleanupStack::Pop(pP);
       
  1324 	return pP;
       
  1325 	}
       
  1326 
       
  1327 CProtocolRef* CProtocolRef::MakeRefL(const TDesC& aName, TServerProtocolDesc* aInfo)
       
  1328 /**
       
  1329 Protocol reference 'constructor'.
       
  1330 This overload of is for "three plane comms" based flows only. It creates a protocol reference
       
  1331 that is then not subject to particular requirements of legacy protocols such as explicit
       
  1332 loading with `RSocketServ::StartProtocol()`
       
  1333 */
       
  1334 	{
       
  1335 	__ASSERT_DEBUG(aInfo, Panic(EBadProtocolDescription));
       
  1336 	User::LeaveIfNull(aInfo);
       
  1337 
       
  1338 	// Create our protocol reference and designate it as being 3PC based
       
  1339 	CProtocolRef* pP = new(ELeave) CProtocolRef;
       
  1340 	pP->SetFlag(EThreePlaneCommsBased);
       
  1341 
       
  1342 	CleanupStack::PushL(pP);
       
  1343 	pP->iTag = aName.AllocL();
       
  1344 	pP->iInfo = *aInfo;
       
  1345 	pP->iFamily = NULL;
       
  1346 
       
  1347 	// Now add it to our global list of protocols
       
  1348 	TSglQue<CProtocolRef>* protList = SockManGlobals::Get()->iProtocols;
       
  1349 
       
  1350 #ifdef _DEBUG
       
  1351 	CProtocolRef* ref = GetProtocolNoCreate(protList, aName);
       
  1352 	if (ref) // uhoh we have a duplicate protocol better panic in debug mode
       
  1353 		{
       
  1354 		LOG( ESockLog::Printf(_L("ERROR in config - duplicate protocol loaded: %S loaded more than once"), &aName));
       
  1355 		Panic(EBadProtocolDescription);
       
  1356 		}
       
  1357 #endif
       
  1358 
       
  1359 	protList->AddLast(*pP);
       
  1360 	CleanupStack::Pop(pP);
       
  1361 	return pP;
       
  1362 	}
       
  1363 
       
  1364 
       
  1365 void CProtocolRef::StartL()
       
  1366 /**
       
  1367 Start the protocol - only once mind lad.
       
  1368 
       
  1369 */
       
  1370 	{
       
  1371 	if (!(iFlags&EStarted))
       
  1372 		{
       
  1373 		iProtocol->StartL();
       
  1374 		iFlags|=EStarted;
       
  1375 		}
       
  1376 	}
       
  1377 
       
  1378 #ifdef __FLOG_ACTIVE
       
  1379 
       
  1380 void TProtocolManagerLogger::LogLoadedInfo()
       
  1381 	{
       
  1382 	CSockManData* globals=SockManGlobals::Get();
       
  1383 	TBuf<256> descList;
       
  1384 	TLogIgnoreOverflow16 overflow;
       
  1385 
       
  1386 	TSglQueIter<CProtocolFamilyRef> j(*globals->iProtocolFamilies);
       
  1387 	CProtocolFamilyRef* f=NULL;
       
  1388 	while(f=j++,f!=NULL)
       
  1389 		{
       
  1390 		if(f->iProtocolFamily)
       
  1391 			{
       
  1392 			descList.AppendFormat(_L(" %08x,"), &overflow, f->iProtocolFamily);
       
  1393 			}
       
  1394 		}
       
  1395 	LOG( ESockLog::Printf(_L("Families (addr):%S"), &descList) );
       
  1396 
       
  1397 	descList.SetLength(0);
       
  1398 	TSglQueIter<CProtocolRef> i(*globals->iProtocols);
       
  1399 	CProtocolRef* p=NULL;
       
  1400 	while(p=i++,p!=NULL)
       
  1401 		{
       
  1402 		if(p->Protocol())
       
  1403 			{
       
  1404 			const TDesC& tag(p->Tag());
       
  1405 			descList.AppendFormat(_L(" %S[%08x],"), &overflow, &tag, p->Family());
       
  1406 			}
       
  1407 		}
       
  1408 	LOG( ESockLog::Printf(_L("Protocols + fam addr:%S"), &descList) );
       
  1409 	}
       
  1410 
       
  1411 #endif