|
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 |