|
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 /** |
|
17 @file SS_SAPSHIM.CPP |
|
18 */ |
|
19 |
|
20 #define SYMBIAN_NETWORKING_UPS |
|
21 #include "ss_sapshim.h" |
|
22 |
|
23 #include <ss_std.h> |
|
24 #include <ss_glob.h> |
|
25 #include <comms-infras/ss_roles.h> |
|
26 #include <comms-infras/ss_log.h> |
|
27 #include <comms-infras/ss_subconnprov.h> |
|
28 #include <comms-infras/ss_connprov.h> |
|
29 #include <ss_protprov.h> |
|
30 #include <ss_sock.h> |
|
31 #include <comms-infras/ss_protflow.h> |
|
32 #include <in_sock.h> // KAfInet |
|
33 #include <elements/nm_messages_child.h> |
|
34 #include <elements/nm_messages_peer.h> |
|
35 |
|
36 #include <comms-infras/nifif.h> |
|
37 #include <comms-infras/nifif_internal.h> |
|
38 |
|
39 #include <addressupdate.h> |
|
40 |
|
41 #include <comms-infras/ss_nodemessages_dataclient.h> |
|
42 #include <comms-infras/ss_nodemessages_flow.h> |
|
43 #include <comms-infras/ss_nodemessages_ipmessages.h> |
|
44 #include <comms-infras/ss_nodemessages_internal_esock.h> |
|
45 |
|
46 #include "ss_protopt.h" |
|
47 |
|
48 #ifdef SYMBIAN_NETWORKING_UPS |
|
49 #include <comms-infras/ss_upsaccesspointconfigext.h> |
|
50 #include <comms-infras/upsmessages.h> |
|
51 |
|
52 |
|
53 #ifdef _DEBUG |
|
54 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
55 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
56 _LIT(KSpecAssert_ESockSSocksspshm, "ESockSSocksspshm"); |
|
57 #endif |
|
58 |
|
59 _LIT_SECURITY_POLICY_C1(KPolicyNetworkServices, ECapabilityNetworkServices); |
|
60 #endif |
|
61 |
|
62 using namespace ESock; |
|
63 using namespace Messages; |
|
64 using namespace MeshMachine; |
|
65 using namespace Factories; |
|
66 |
|
67 //CHostResolver specific functions this is to remove once we have app layer protocols |
|
68 //*************************************************************************************** |
|
69 //also loo for iHostResolverNotify |
|
70 MLowerControl* CTransportFlowShim::GetControlL(const TDesC8& /*aProtocol*/) |
|
71 { |
|
72 return this; |
|
73 } |
|
74 |
|
75 TInt CTransportFlowShim::Control(TUint aLevel, TUint aName, TDes8& aOption) |
|
76 { |
|
77 return iLowerControl ? iLowerControl->Control(aLevel, aName, aOption) : KErrNotReady; |
|
78 } |
|
79 |
|
80 MLowerDataSender* CTransportFlowShim::BindL(const TDesC8& /*aProtocol*/, MUpperDataReceiver* aReceiver, MUpperControl* aControl) |
|
81 { |
|
82 if (aReceiver || iProvider || IsBoundToSession()) |
|
83 { |
|
84 User::Leave(KErrInUse); |
|
85 } |
|
86 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef()); |
|
87 iHostResolverNotify = aControl; |
|
88 return this; |
|
89 } |
|
90 |
|
91 void CTransportFlowShim::Unbind( MUpperDataReceiver* /*aReceiver*/, MUpperControl* aControl) |
|
92 { |
|
93 (void)aControl; |
|
94 __ASSERT_DEBUG(aControl == iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 1)); |
|
95 __ASSERT_DEBUG(iDCIdle <= EClientsPresent, User::Panic(KSpecAssert_ESockSSocksspshm, 2)); |
|
96 iDCIdle = EIdle; |
|
97 iHostResolverNotify = NULL; |
|
98 if(iSubConnectionProvider.IsOpen()) // legacy flows have no control side |
|
99 { |
|
100 ProcessDCIdleState(); |
|
101 } |
|
102 } |
|
103 |
|
104 MLowerDataSender::TSendResult CTransportFlowShim::Send(RMBufChain& /*aData*/) |
|
105 { |
|
106 __ASSERT_DEBUG(iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 3)); |
|
107 |
|
108 TBuf8<sizeof(TConnectionInfo)> buf; |
|
109 if (Control(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), buf) == KErrNone) |
|
110 { |
|
111 iHostResolverNotify->StartSending(); |
|
112 } |
|
113 else if (!iLowerControl) |
|
114 { |
|
115 #ifdef SYMBIAN_NETWORKING_UPS |
|
116 TInt result = SetupForNoBearerOnSend(); |
|
117 if (result != KErrNone) |
|
118 { |
|
119 return TSendResult(result); |
|
120 } |
|
121 #endif |
|
122 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 4)); // legacy flows have no control side, so must never get here |
|
123 PostNoBearer(); |
|
124 } |
|
125 |
|
126 return MLowerDataSender::ESendAccepted; |
|
127 } |
|
128 //*************************************************************************************** |
|
129 //End of CHostResolver specific functions also look for iHostResolverNotify to find the rest |
|
130 |
|
131 #ifndef SYMBIAN_NETWORKING_UPS |
|
132 |
|
133 // |
|
134 // Not used with UPS support - CUpsTransportFlowShim::NewL() used instead. |
|
135 // |
|
136 |
|
137 CTransportFlowShim* CTransportFlowShim::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
138 { |
|
139 return new (ELeave) CTransportFlowShim(aFactory, aSubConn, aProtocolIntf); |
|
140 } |
|
141 |
|
142 #endif |
|
143 |
|
144 CTransportFlowShim::CTransportFlowShim(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
145 : CNetworkFlow(aFactory, aSubConn, aProtocolIntf), iFlowParams(TFlowParams(NULL, NULL, KUndefinedProtocol, NULL, NULL)) |
|
146 { |
|
147 LOG_NODE_CREATE(KESockFlowTag, CTransportFlowShim) |
|
148 } |
|
149 |
|
150 |
|
151 void CTransportFlowShim::SetSSP(CServProviderBase& aSSP) |
|
152 { |
|
153 __ASSERT_DEBUG(iProvider == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 5)); |
|
154 iProvider = &aSSP; |
|
155 iProvider->SetNotify(this); |
|
156 } |
|
157 |
|
158 CTransportFlowShim::~CTransportFlowShim() |
|
159 { |
|
160 // Remove ourselves from any listening control session's accept queue. |
|
161 if(iListenerControlNotify) |
|
162 { |
|
163 iListenerControlNotify->DisconnectFromListener(*this); |
|
164 } |
|
165 |
|
166 if(!iDetaching) |
|
167 { |
|
168 delete iProvider; |
|
169 iProvider = NULL; |
|
170 } |
|
171 |
|
172 Messages::TEBase::TError err(TEBase::TNull::Id(), KErrBindersInvalid); |
|
173 SubConnectionError(err, EErrorAllOperations); |
|
174 |
|
175 LOG_NODE_DESTROY(KESockFlowTag, CTransportFlowShim) |
|
176 } |
|
177 |
|
178 void CTransportFlowShim::SetSockType(TUint aSockType) |
|
179 { |
|
180 if (iProvider) |
|
181 { |
|
182 iProvider->SetSockType(aSockType); |
|
183 } |
|
184 } |
|
185 |
|
186 MSessionControl* CTransportFlowShim::GetControlL(TInt aSessionType,MSessionControlNotify& aSessionControlNotify) |
|
187 { |
|
188 CNetworkFlow::GetControlL(aSessionType,aSessionControlNotify); |
|
189 SetSockType(aSessionType); |
|
190 return this; |
|
191 } |
|
192 |
|
193 MSessionData* CTransportFlowShim::BindL(MSessionDataNotify& aNotify) |
|
194 { |
|
195 LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tBindL(aNotify 0x%08x)"), this, &aNotify) ); |
|
196 |
|
197 // The flow shim now manages custody and loading of the protocol involved. |
|
198 // However in the case of host resolvers, until ported for the same behaviour, protocol loading is still managed by the socket. |
|
199 if(iFlowParams.iFlowLoadsProtocol) |
|
200 { |
|
201 CProtocolRef * protocolReference = ProtocolManager::FindProtocolL( |
|
202 iFlowParams.iAddrFamily, |
|
203 iFlowParams.iSocketType, |
|
204 iFlowParams.iProtocol); |
|
205 |
|
206 if (protocolReference->GetFlag() & CProtocolRef::EThreePlaneCommsBased) |
|
207 { |
|
208 // Three plane comms protos should not be seen here. If an RSocket is opened with a supported |
|
209 // protocol and it happens to be 3PC this point will be reached. In the case of RTP some |
|
210 // special processing is performed (in the SCPR) in order to sort out the mess and ensure that |
|
211 // a UDP/TCP flow is requested instead. |
|
212 User::Leave(KErrProtocolNotReady); |
|
213 } |
|
214 |
|
215 // Check if the protocol is supported over sockets |
|
216 if (!(protocolReference->Info().iServiceTypeInfo & ESocketSupport)) |
|
217 { |
|
218 User::Leave(KErrNotSupported); |
|
219 } |
|
220 |
|
221 // Have the protocol loaded if not already the case and confirm it has socket support |
|
222 protocolReference->LoadAndBindL(); |
|
223 |
|
224 __ASSERT_DEBUG(iProtocolReference == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 6)); |
|
225 iProtocolReference = protocolReference; |
|
226 |
|
227 // Have the protocol added to the list of protocols for the session it is associated with |
|
228 CSockSessionProxy* sessionProxy = reinterpret_cast<CSockSessionProxy*>(iFlowParams.iSessionProxy); |
|
229 if(sessionProxy != NULL) |
|
230 { |
|
231 sessionProxy->AddProtocolL(iProtocolReference->Protocol()); |
|
232 } |
|
233 |
|
234 // Fetch a new SAP from the protocol for this flow |
|
235 if (iProvider == NULL) |
|
236 { |
|
237 iProvider = iProtocolReference->Protocol()->NewSAPL(iFlowParams.iSocketType); |
|
238 |
|
239 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
240 // Set the options iterating the RArray variable |
|
241 SetProtocolOptions(); |
|
242 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
243 |
|
244 if (iProvider) |
|
245 { |
|
246 iProvider->SetNotify(this); |
|
247 } |
|
248 } |
|
249 } |
|
250 |
|
251 // Now perform the binding proper |
|
252 if (!iProvider) |
|
253 { |
|
254 User::Leave(KErrNotSupported); |
|
255 } |
|
256 |
|
257 __ASSERT_DEBUG(!iHostResolverNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 8)); |
|
258 CNetworkFlow::BindL(aNotify); |
|
259 iProvider->SetNotify(this); |
|
260 |
|
261 return this; |
|
262 } |
|
263 |
|
264 void CTransportFlowShim::Unbind() |
|
265 { |
|
266 LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tUnbind()"), this) ); |
|
267 |
|
268 // Infant mortality case in which binding never completed, |
|
269 if(iFlowParams.iProtocol == KUndefinedProtocol) |
|
270 { |
|
271 delete this; |
|
272 return; |
|
273 } |
|
274 |
|
275 // Legacy support for host resolvers |
|
276 if(iHostResolverNotify) |
|
277 { |
|
278 __ASSERT_DEBUG(!iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 9)); // can't have both HR & SAP |
|
279 |
|
280 LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tUnbind(): iBearerExpected %d"), this, iBearerExpected) ); |
|
281 if (!iBearerExpected) |
|
282 { |
|
283 delete this; |
|
284 } |
|
285 else |
|
286 { |
|
287 iDeleteUponBearerReception = ETrue; |
|
288 iHostResolverNotify = NULL; |
|
289 } |
|
290 return; |
|
291 } |
|
292 |
|
293 if (iProvider) |
|
294 { |
|
295 iProvider->SetNotify(NULL); |
|
296 |
|
297 if (!iDetaching) |
|
298 { |
|
299 delete iProvider; |
|
300 iProvider = NULL; |
|
301 } |
|
302 } |
|
303 |
|
304 #ifdef SYMBIAN_NETWORKING_UPS |
|
305 // Hook for derived classes to do cleanup before unbind occurs |
|
306 PreUnbind(); |
|
307 #endif |
|
308 |
|
309 CNetworkFlow::Unbind(); |
|
310 } |
|
311 |
|
312 ESock::CSubConnectionFlowBase& CTransportFlowShim::CloneFlowL() |
|
313 { |
|
314 __ASSERT_DEBUG(iProtocolIntf, User::Panic(KSpecAssert_ESockSSocksspshm, 10)); |
|
315 TDefaultFlowFactoryQuery query (iProtocolIntf->ControlProviderId(), iSubConnectionProvider.RecipientId()); |
|
316 ESock::CSubConnectionFlowBase& flow = static_cast<ESock::CSubConnectionFlowBase&>(*(Factory().CreateObjectL(query))); |
|
317 // Legacy flows lack a control provider |
|
318 if(iSubConnectionProvider.IsOpen()) |
|
319 { |
|
320 TCFPeer::TJoinRequest msg(flow.Id(), TClientType(TCFClientType::EData, TCFClientType::EActive)); |
|
321 iSubConnectionProvider.PostMessage(Id(), msg); |
|
322 } |
|
323 return flow; |
|
324 } |
|
325 |
|
326 void CTransportFlowShim::Start() |
|
327 /** |
|
328 Start a service provider. |
|
329 */ |
|
330 { |
|
331 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 11)); |
|
332 iProvider->Start(); |
|
333 } |
|
334 |
|
335 void CTransportFlowShim::LocalName(TSockAddr& anAddr) const |
|
336 /** Gets the local name (address) of the socket service provider entity. The format |
|
337 of the data in the TSockAddr object is defined by individual protocols. |
|
338 |
|
339 The local address is the address of the local machine plus a local port number. |
|
340 Generally only the port number is important, unless you have two IP interfaces, |
|
341 for example. |
|
342 |
|
343 @param anAddr The address to be filled in */ |
|
344 { |
|
345 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 12)); |
|
346 iProvider->LocalName(anAddr); |
|
347 } |
|
348 |
|
349 void CTransportFlowShim::SetLocalName(TSockAddr& anAddr) |
|
350 /** Sets the local name (address) of the socket service provider entity. The format |
|
351 of the data in the TSockAddr object is defined by individual protocols. |
|
352 |
|
353 @param anAddr The address */ |
|
354 { |
|
355 CNetworkFlow::SetLocalName(anAddr); |
|
356 PostDataClientRouted(); |
|
357 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 65)); |
|
358 TInt err = iProvider->SetLocalName(anAddr); |
|
359 if (err != KErrNone) |
|
360 { |
|
361 // Post TError to self, which will result in SubConnectionError to |
|
362 // be called in the TError handling. Have to fake that the message is |
|
363 // coming from iSubConnectionProvider otherwise ReceivedL will leave. |
|
364 RClientInterface::OpenPostMessageClose(iSubConnectionProvider.RecipientId(), Id(), TEBase::TError(err).CRef()); |
|
365 return; |
|
366 } |
|
367 |
|
368 SetLocalNameProcess(); |
|
369 } |
|
370 |
|
371 void CTransportFlowShim::SetLocalNameProcess() |
|
372 { |
|
373 TBool bearerSent = EFalse; |
|
374 if(iFlowParams.iFlowRequestType != TFlowParams::EImplicit) |
|
375 { |
|
376 // For explicit sockets, TNoBearer will be sent out if it has not already |
|
377 // been done so. This was introduced for PREQ2279, as it is necessary |
|
378 // to lock this SAP to an interface for incoming sockets. Once locked, |
|
379 // this ensures that any incoming packets are only accepted over the locked down |
|
380 // interface and no other interfaces. To lock the interface down the |
|
381 // NoBearer sequence is executed. This change will also now apply to |
|
382 // outgoing explicit sockets. The change for outgoing explicit sockets is |
|
383 // that the NoBearer sequence is started here instead of when receiving |
|
384 // a NoBearer upcall from the protocol. |
|
385 |
|
386 // Attempt to send out TNoBearer. |
|
387 if (DoNoBearer()) |
|
388 { |
|
389 // TNoBearer was sent out. |
|
390 bearerSent = ETrue; |
|
391 } |
|
392 } |
|
393 |
|
394 if (!bearerSent) |
|
395 { |
|
396 // No Bearer was already sent out earlier, or this is an implicit socket. |
|
397 iSessionControlNotify->SetLocalNameComplete(); |
|
398 } |
|
399 } |
|
400 |
|
401 |
|
402 TBool CTransportFlowShim::DoNoBearer() |
|
403 /** |
|
404 Do the actual no Bearer call. |
|
405 @return ETrue if the NoBearer post was actually done, EFalse otherwise |
|
406 */ |
|
407 { |
|
408 TInt ret = EFalse; |
|
409 if(!iIsStopped) |
|
410 { // Prevent sending NoBearer if DataClientStop was received |
|
411 if (LockToConnectionInfo() != KErrNone) |
|
412 { |
|
413 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 66)); |
|
414 PostNoBearer(); |
|
415 ret = ETrue; |
|
416 } |
|
417 iUseBearerErrors = EFalse; |
|
418 ClearDataClientRoutedGuard(); |
|
419 } |
|
420 return ret; |
|
421 } |
|
422 |
|
423 |
|
424 |
|
425 void CTransportFlowShim::RemName(TSockAddr& anAddr) const |
|
426 /** Gets the remote name (address) of the socket service provider entity. The format |
|
427 of the data in the TSockAddr object is defined by individual protocols. |
|
428 |
|
429 A remote address is either the address you're sending data to (non connection-oriented |
|
430 sockets)* or the remote end of the connection. It is the address of the remote |
|
431 machine (your peer in the network) plus a port number. |
|
432 |
|
433 @note RemName is only meaningful if the socket server client has called Connect() |
|
434 to set up a default address for SendTo(). This function will only be called |
|
435 on the protocol if this is the case. |
|
436 |
|
437 @param anAddr The address to be filled in */ |
|
438 { |
|
439 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 14)); |
|
440 iProvider->RemName(anAddr); |
|
441 } |
|
442 |
|
443 TInt CTransportFlowShim::SetRemName(TSockAddr& anAddr) |
|
444 /** Sets the remote name (address) of the socket service provider entity. The format |
|
445 of the data in the TSockAddr object is defined by individual protocols. |
|
446 |
|
447 @param anAddr The address |
|
448 @return Returns KErrNone if the remote name is correctly set or, if this is |
|
449 not the case, an informative error number. */ |
|
450 { |
|
451 CNetworkFlow::SetRemName(anAddr); |
|
452 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 15)); |
|
453 return iProvider->SetRemName(anAddr); |
|
454 } |
|
455 |
|
456 TInt CTransportFlowShim::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const |
|
457 /** Gets some protocol specific option when called by the socket server on behalf of a |
|
458 client. A protocol may pass the request down a protocol stack (to protocols it is bound |
|
459 to) using the GetOption() function of CProtocolBase. |
|
460 |
|
461 @param aLevel Option level. |
|
462 @param aName Option name. |
|
463 @param anOption Option data. |
|
464 @return System wide error code. |
|
465 */ |
|
466 { |
|
467 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 16)); |
|
468 return iProvider->GetOption(aLevel, aName, anOption); |
|
469 } |
|
470 |
|
471 void CTransportFlowShim::Ioctl(TUint aLevel, TUint aName, TDes8* anOption) |
|
472 /** Performs some protocol specific IO control. |
|
473 |
|
474 @note If this function is called erroneously, the protocol should call Error() on the |
|
475 socket. If an Ioctl call is already outstanding, the client will be panicked with the |
|
476 value ETwoIoctls. |
|
477 |
|
478 @param aLevel Option level. |
|
479 @param aName Option name. |
|
480 @param anOption Option data. |
|
481 */ |
|
482 { |
|
483 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 17)); |
|
484 iProvider->Ioctl(aLevel, aName, anOption); |
|
485 } |
|
486 |
|
487 void CTransportFlowShim::CancelIoctl(TUint aLevel, TUint aName) |
|
488 /** Cancels an outstanding Ioctl call. You are guaranteed only to have one outstanding |
|
489 at once. |
|
490 |
|
491 @param aLevel IOCTL level. |
|
492 @param aName IOCTL name. |
|
493 */ |
|
494 { |
|
495 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 18)); |
|
496 iProvider->CancelIoctl(aLevel, aName); |
|
497 } |
|
498 |
|
499 TInt CTransportFlowShim::SetOption(TUint aLevel, TUint aName, const TDesC8 &anOption) |
|
500 /** Sets some protocol specific option when called by the socket server on behalf of a |
|
501 client. A protocol may pass the request down a protocol stack (to protocols it is bound |
|
502 to) using the SetOption() function of CProtocolBase. |
|
503 |
|
504 @param aLevel Option level. |
|
505 @param aName Option name. |
|
506 @param anOption Option data. |
|
507 @return System wide error code. |
|
508 */ |
|
509 { |
|
510 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 19)); |
|
511 return iProvider->SetOption(aLevel, aName, anOption); |
|
512 } |
|
513 |
|
514 void CTransportFlowShim::ActiveOpen() |
|
515 /** Initiates a connection operation - this means that it tells the protocol to |
|
516 attempt to connect to a peer. It is called by the socket server in response |
|
517 to a connect request from a client. |
|
518 |
|
519 This version of the function has user data in the connection frame. |
|
520 |
|
521 Only ever called on connection-oriented sockets. Such a socket |
|
522 should always have both the local address and the remote address specified |
|
523 before this function is called. If this is not the case then the protocol |
|
524 should panic. |
|
525 |
|
526 When a connection has completed, the protocol should call ConnectComplete() |
|
527 on its TNotify. If an error occurs during connection the protocol should not |
|
528 call ConnectComplete() at all; instead it should call Error(). |
|
529 */ |
|
530 { |
|
531 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 20)); |
|
532 iProvider->ActiveOpen(); |
|
533 } |
|
534 |
|
535 void CTransportFlowShim::ActiveOpen(const TDesC8& aConnectionData) |
|
536 /** Initiates a connection operation - this means that it tells the protocol to |
|
537 attempt to connect to a peer. It is called by the socket server in response |
|
538 to a connect request from a client. |
|
539 |
|
540 This version of the function has user data in the connection frame. |
|
541 |
|
542 Only ever called on connection-oriented sockets. Such a socket |
|
543 should always have both the local address and the remote address specified |
|
544 before this function is called. If this is not the case then the protocol |
|
545 should panic. |
|
546 |
|
547 When a connection has completed, the protocol should call ConnectComplete() |
|
548 on its TNotify. If an error occurs during connection the protocol should not |
|
549 call ConnectComplete() at all; instead it should call Error(). |
|
550 |
|
551 @param aConnectionData If the protocol supports user specified connection |
|
552 data, then it will be held in this buffer. */ |
|
553 { |
|
554 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 21)); |
|
555 iProvider->ActiveOpen(aConnectionData); |
|
556 } |
|
557 |
|
558 TInt CTransportFlowShim::PassiveOpen(TUint aQueueSize) |
|
559 /** Tells the protocol to start waiting for an incoming connection request on this |
|
560 socket (i.e. port). It is called by the socket server in response to a listen |
|
561 request from a client. |
|
562 |
|
563 Only ever called on connection-oriented sockets. Such a socket |
|
564 should always have both the local address and the remote address specified |
|
565 before this function is called. If this is not the case, then the protocol |
|
566 should panic. |
|
567 |
|
568 The aQue parameter is the number of sockets which can be waiting for an outstanding |
|
569 Start after calling ConnectComplete(). The protocol should keep a count of |
|
570 sockets in this state - incrementing a variable in ConnectComplete(), and |
|
571 decrementing it in Start(). |
|
572 |
|
573 When a connection has completed, the protocol should call ConnectComplete() |
|
574 on its TNotify. If an error occurs during connection the protocol should not |
|
575 call ConnectComplete() at all; instead it should call Error(). |
|
576 |
|
577 @param aQueSize Size of connect queue. |
|
578 */ |
|
579 { |
|
580 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 22)); |
|
581 return iProvider->PassiveOpen(aQueueSize); |
|
582 } |
|
583 |
|
584 TInt CTransportFlowShim::PassiveOpen(TUint aQueueSize, const TDesC8& aConnectionData) |
|
585 /** Tells the protocol to start waiting for an incoming connection request on this |
|
586 socket (i.e. port). It is called by the socket server in response to a listen |
|
587 request from a client. |
|
588 |
|
589 This version of the function has user data in the connection frame. |
|
590 |
|
591 Only ever called on connection-oriented sockets. Such a socket |
|
592 should always have both the local address and the remote address specified |
|
593 before this function is called. If this is not the case then the protocol |
|
594 should panic. |
|
595 |
|
596 The aQue parameter is the number of sockets which can be waiting for an outstanding |
|
597 Start after calling ConnectComplete(). The protocol should keep a count of |
|
598 sockets in this state - incrementing a variable in ConnectComplete(), and |
|
599 decrementing it in Start(). |
|
600 |
|
601 When a connection has completed the protocol should call ConnectComplete() |
|
602 on its TNotify. If an error occurs during connection the protocol should not |
|
603 call ConnectComplete() at all; instead it should call Error(). |
|
604 |
|
605 @param aQueueSize size of connect queue |
|
606 @param aConnectionData if the protocol supports user specified connection data |
|
607 then it will be held in this buffer. */ |
|
608 { |
|
609 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 23)); |
|
610 return iProvider->PassiveOpen(aQueueSize, aConnectionData); |
|
611 } |
|
612 |
|
613 void CTransportFlowShim::Shutdown(MSessionControl::TCloseType aOption) |
|
614 /** Terminates a connection (or closes a non connection-oriented socket down). |
|
615 |
|
616 The value of the option argument specifies the type of processing which will |
|
617 be required of the protocol after this function is called. |
|
618 |
|
619 Normally, when the socket server has called Shutdown() for a socket, it will |
|
620 wait for the socket to call CanClose() before destroying the CServProviderBase |
|
621 object. However, if the option argument is EImmediate, the CServProviderBase |
|
622 will be destroyed as soon as Shutdown() returns. |
|
623 |
|
624 @param option The shutdown type. */ |
|
625 { |
|
626 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 24)); |
|
627 if (aOption == MSessionControl::EImmediate) |
|
628 { |
|
629 iShuttingDown = ETrue; |
|
630 } |
|
631 |
|
632 // It is possible for the provider to be null if an error occurs immediatly |
|
633 // after socket creation before the flow is bound and the provider is received |
|
634 // from the protocol. |
|
635 if(iProvider) |
|
636 { |
|
637 iProvider->Shutdown(CServProviderBase::TCloseType(aOption)); |
|
638 } |
|
639 } |
|
640 |
|
641 void CTransportFlowShim::Shutdown(MSessionControl::TCloseType aOption, const TDesC8& aDisconnectionData) |
|
642 /** Terminates a connection (or closes a non connection-oriented socket down). |
|
643 |
|
644 The value of the option argument specifies the type of processing which will |
|
645 be required of the protocol after this function is called. |
|
646 |
|
647 Normally, when the socket server has called Shutdown() for a socket, it will |
|
648 wait for the socket to call CanClose() before destroying the CServProviderBase |
|
649 object. However, if the option argument is EImmediate, the CServProviderBase |
|
650 will be destroyed as soon as Shutdown() returns. |
|
651 |
|
652 @param option The shutdown type. |
|
653 @param aDisconnectionData If the protocol supports disconnect data, any such |
|
654 data required will be held in this buffer. */ |
|
655 { |
|
656 // It is possible for the provider to be null if an error occurs immediatly |
|
657 // after socket creation before the flow is bound and the provider is received |
|
658 // from the protocol. |
|
659 if(iProvider) |
|
660 { |
|
661 iProvider->Shutdown(CServProviderBase::TCloseType(aOption), aDisconnectionData); |
|
662 } |
|
663 } |
|
664 |
|
665 void CTransportFlowShim::AutoBind() |
|
666 /** Specifies that the protocol should choose a local address for the service access |
|
667 point itself. */ |
|
668 { |
|
669 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 25)); |
|
670 iProvider->AutoBind(); |
|
671 SetLocalNameProcess(); |
|
672 |
|
673 } |
|
674 |
|
675 TUint CTransportFlowShim::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* anAddr) |
|
676 /** Sends data onto the network via the protocol. |
|
677 |
|
678 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has |
|
679 been called on their MSocketNotify before Write() is called). |
|
680 |
|
681 The socket server keeps track of how much data is waiting and then tries to send it all |
|
682 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than |
|
683 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it |
|
684 is ready to send more data. |
|
685 |
|
686 anAddr is the address to write the data to. Connection oriented sockets always use the |
|
687 default value. |
|
688 |
|
689 @param aDesc The data to be sent. |
|
690 @param aOptions Protocol specific options. |
|
691 @param anAddr Address to write the data to. |
|
692 |
|
693 @returns For stream-oriented protocols the return value is the number of bytes actually written. |
|
694 If this is less than the length of the descriptor then the protocol should call CanSend() |
|
695 when it is ready to send more data. For datagram-oriented protocols, the write should return |
|
696 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds - |
|
697 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is |
|
698 ready to send more data. If the Write() fails due to some error, then it should call Error() with |
|
699 an informative error number. |
|
700 */ |
|
701 { |
|
702 CNetworkFlow::Write( aDesc, aOptions, anAddr); |
|
703 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 26)); |
|
704 return iProvider->Write(aDesc, aOptions, anAddr); |
|
705 } |
|
706 |
|
707 TInt CTransportFlowShim::Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr) |
|
708 /** Sends data onto the network via the protocol. |
|
709 |
|
710 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has |
|
711 been called on their MSocketNotify before Write() is called). |
|
712 |
|
713 The socket server keeps track of how much data is waiting and then tries to send it all |
|
714 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than |
|
715 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it |
|
716 is ready to send more data. |
|
717 |
|
718 anAddr is the address to write the data to. Connection oriented sockets always use the |
|
719 default value. |
|
720 |
|
721 @param aData The data to be sent. |
|
722 @param aOptions Protocol specific options. |
|
723 @param anAddr Address to write the data to. |
|
724 |
|
725 @returns For stream-oriented protocols the return value is the number of bytes actually written. |
|
726 If this is less than the length of the descriptor then the protocol should call CanSend() |
|
727 when it is ready to send more data. For datagram-oriented protocols, the write should return |
|
728 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds - |
|
729 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is |
|
730 ready to send more data. If the Write() fails due to some error, then it should call Error() with |
|
731 an informative error number. |
|
732 */ |
|
733 { |
|
734 CNetworkFlow::Write(aData, aOptions, anAddr); |
|
735 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 27)); |
|
736 return iProvider->Write(aData, aOptions, anAddr); |
|
737 } |
|
738 |
|
739 void CTransportFlowShim::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* anAddr) |
|
740 /** Gets data which the protocol has indicated is waiting in its buffers using the NewData |
|
741 up-call on the MSocketNotify. |
|
742 |
|
743 GetData() will only ever be called for as much data as the protocol has specified it can process |
|
744 using the NewData up-call. |
|
745 |
|
746 For stream oriented protocols GetData() should fill the descriptor with data from the stream. On |
|
747 a datagram protocol GetData() should copy one datagram into the descriptor and set the length of |
|
748 the descriptor. If a full datagram will not fit into the supplied descriptor, the overflow should |
|
749 be discarded. |
|
750 |
|
751 anAddr should be filled in by the protocol with the address of where the data came from. |
|
752 |
|
753 @param aDesc The buffer for data. |
|
754 @param aOptions Protocol specific options. |
|
755 @param anAddr Address where the data came from. |
|
756 */ |
|
757 { |
|
758 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 28)); |
|
759 iProvider->GetData(aDesc, aOptions, anAddr); |
|
760 } |
|
761 |
|
762 TInt CTransportFlowShim::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr) |
|
763 /** Gets data which the protocol has indicated is waiting in its buffers using the NewData |
|
764 up-call on the MSocketNotify. |
|
765 |
|
766 GetData() will only ever be called for as much data as the protocol has specified it can process |
|
767 using the NewData up-call. |
|
768 |
|
769 For stream oriented protocols GetData() should fill the descriptor with data from the stream. On |
|
770 a datagram protocol GetData() should copy one datagram into the descriptor and set the length of |
|
771 the descriptor. If a full datagram will not fit into the supplied descriptor, the overflow should |
|
772 be discarded. |
|
773 |
|
774 anAddr should be filled in by the protocol with the address of where the data came from. |
|
775 |
|
776 @param aDesc The buffer for data. |
|
777 @param aOptions Protocol specific options. |
|
778 @param anAddr Address where the data came from. |
|
779 */ |
|
780 { |
|
781 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 29)); |
|
782 return iProvider->GetData(aData, aLength, aOptions, anAddr); |
|
783 } |
|
784 |
|
785 TInt CTransportFlowShim::SecurityCheck(MProvdSecurityChecker* aChecker) |
|
786 /** |
|
787 Ask the SAP provider to perform a security policy check on the client process (default implementation). |
|
788 */ |
|
789 { |
|
790 // ******************************************************************** |
|
791 // NOTE: KErrNone for now, but this should be changed to KErrNotSupported to |
|
792 // turn on strict checking and fail PRTs that have not been secured. |
|
793 // ******************************************************************** |
|
794 |
|
795 __ASSERT_DEBUG(iProvider, User::Panic(KSpecAssert_ESockSSocksspshm, 30)); |
|
796 return iProvider->SecurityCheck(aChecker); |
|
797 } |
|
798 |
|
799 void CTransportFlowShim::NewData(TUint aCount) |
|
800 { |
|
801 __ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 31)); |
|
802 iSessionDataNotify->NewData(aCount); |
|
803 } |
|
804 |
|
805 void CTransportFlowShim::CanSend() |
|
806 { |
|
807 __ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 32)); |
|
808 iSessionDataNotify->CanSend(); |
|
809 } |
|
810 |
|
811 void CTransportFlowShim::ConnectComplete() |
|
812 { |
|
813 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 33)); |
|
814 iSessionControlNotify->ConnectComplete(); |
|
815 } |
|
816 |
|
817 void CTransportFlowShim::ConnectComplete(const TDesC8& aConnectData) |
|
818 { |
|
819 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 34)); |
|
820 iSessionControlNotify->ConnectComplete(aConnectData); |
|
821 } |
|
822 |
|
823 CTransportFlowShim* CTransportFlowShim::CloneNSetSAP(CServProviderBase& aSSP) |
|
824 { |
|
825 //Here we can afford to create a flow directly since we know sub-connection |
|
826 //+ protocols & flow plug-is've been already loaded while opening listenning socket |
|
827 //this is the only case when flow joins without being created from control side |
|
828 CTransportFlowShim* shimFlow = NULL; |
|
829 TRAPD(ret,shimFlow = factoryobject_cast<CTransportFlowShim>(&CloneFlowL())); |
|
830 if (ret != KErrNone) |
|
831 { |
|
832 Error(ret,MSessionControlNotify::EErrorCompleteConnect); |
|
833 } |
|
834 else |
|
835 { |
|
836 __ASSERT_DEBUG(shimFlow, User::Panic(KSpecAssert_ESockSSocksspshm, 35)); //otherwise we shouldn't be here |
|
837 shimFlow->SetSSP(aSSP); |
|
838 shimFlow->iFlowParams = iFlowParams; |
|
839 } |
|
840 return shimFlow; |
|
841 } |
|
842 |
|
843 void CTransportFlowShim::ConnectComplete(CServProviderBase& aSSP) |
|
844 { |
|
845 CTransportFlowShim* shimFlow; |
|
846 if ((shimFlow = CloneNSetSAP(aSSP)) != NULL) |
|
847 { |
|
848 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 36)); |
|
849 |
|
850 // Store a pointer to the listening control session in case we need to unbind before |
|
851 // the passively opened socket is accepted. |
|
852 shimFlow->iListenerControlNotify = iSessionControlNotify; |
|
853 |
|
854 iSessionControlNotify->ConnectComplete(*shimFlow); |
|
855 } |
|
856 } |
|
857 |
|
858 void CTransportFlowShim::ConnectComplete(CServProviderBase& aSSP,const TDesC8& aConnectData) |
|
859 { |
|
860 // CTransportFlowShim* shim = NULL; |
|
861 // TRAPD(ret, shim = CTransportFlowShim::NewL(aSSP, NULL, iProtocolId)); |
|
862 |
|
863 CTransportFlowShim* shimFlow; |
|
864 if ((shimFlow = CloneNSetSAP(aSSP)) != NULL) |
|
865 { |
|
866 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 37)); |
|
867 iSessionControlNotify->ConnectComplete(*shimFlow, aConnectData); |
|
868 } |
|
869 } |
|
870 |
|
871 void CTransportFlowShim::CanClose(MSocketNotify::TDelete aDelete) |
|
872 { |
|
873 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() aDelete %d"), this, aDelete) ); |
|
874 |
|
875 if(iSessionControlNotify) |
|
876 { |
|
877 iDetaching = aDelete == MSocketNotify::EDetach; |
|
878 iSessionControlNotify->CanClose(MSessionControlNotify::TDelete(aDelete)); |
|
879 if(aDelete==MSocketNotify::EDetach) |
|
880 { |
|
881 iProvider = NULL; |
|
882 } |
|
883 } |
|
884 else |
|
885 { |
|
886 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) ); |
|
887 |
|
888 // No control above us - likely cause is that we're the result of a passive open that |
|
889 // hasn't yet been accepted. |
|
890 Unbind(); |
|
891 } |
|
892 } |
|
893 |
|
894 void CTransportFlowShim::CanClose(const TDesC8& aDisconnectData,MSocketNotify::TDelete aDelete) |
|
895 { |
|
896 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() aDisconnectData %08x, aDelete %d"), this, aDisconnectData.Ptr(), aDelete) ); |
|
897 |
|
898 if(iSessionControlNotify) |
|
899 { |
|
900 iDetaching = aDelete == MSocketNotify::EDetach; |
|
901 iSessionControlNotify->CanClose(aDisconnectData, MSessionControlNotify::TDelete(aDelete)); |
|
902 if(aDelete==MSocketNotify::EDetach) |
|
903 { |
|
904 iProvider = NULL; |
|
905 } |
|
906 } |
|
907 else |
|
908 { |
|
909 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tCanClose() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) ); |
|
910 |
|
911 // No control above us - likely cause is that we're the result of a passive open that |
|
912 // hasn't yet been accepted. |
|
913 Unbind(); |
|
914 } |
|
915 } |
|
916 |
|
917 void CTransportFlowShim::Error(TInt anError, TUint anOperationMask) |
|
918 { |
|
919 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tError() anError %d, anOperationMask %d"), this, anError, anOperationMask) ); |
|
920 |
|
921 NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=Error(%d)"), |
|
922 this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), anError) ) |
|
923 |
|
924 if(iSessionControlNotify) |
|
925 { |
|
926 if (iSessionControlNotify->Error(anError, anOperationMask) != KErrNone) |
|
927 { |
|
928 if (iLowerFlow) |
|
929 { |
|
930 iLowerFlow->Unbind(NULL,NULL); |
|
931 iLowerFlow = NULL; |
|
932 } |
|
933 iLowerControl = NULL; |
|
934 } |
|
935 } |
|
936 else |
|
937 { |
|
938 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tError() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) ); |
|
939 |
|
940 // No control above us - likely cause is that we're the result of a passive open that |
|
941 // hasn't yet been accepted. |
|
942 iDetaching = MSocketNotify::EDetach; |
|
943 Unbind(); |
|
944 } |
|
945 } |
|
946 |
|
947 void CTransportFlowShim::Disconnect(void) |
|
948 { |
|
949 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect()"), this) ); |
|
950 |
|
951 if(iSessionControlNotify) |
|
952 { |
|
953 iSessionControlNotify->Disconnect(); |
|
954 } |
|
955 else |
|
956 { |
|
957 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) ); |
|
958 |
|
959 // No control above us - likely cause is that we're the result of a passive open that |
|
960 // hasn't yet been accepted. |
|
961 iDetaching = MSocketNotify::EDetach; |
|
962 Unbind(); |
|
963 } |
|
964 } |
|
965 |
|
966 void CTransportFlowShim::Disconnect(TDesC8& aDisconnectData) |
|
967 { |
|
968 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() aDisconnectData %08x"), this, aDisconnectData.Ptr()) ); |
|
969 |
|
970 if(iSessionControlNotify) |
|
971 { |
|
972 iSessionControlNotify->Disconnect(aDisconnectData); |
|
973 } |
|
974 else |
|
975 { |
|
976 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tDisconnect() no control above us to notify (open was likely passive and has not been accepted yet) so simply unbinding"), this) ); |
|
977 |
|
978 // No control above us - likely cause is that we're the result of a passive open that |
|
979 // hasn't yet been accepted. |
|
980 iDetaching = MSocketNotify::EDetach; |
|
981 Unbind(); |
|
982 } |
|
983 } |
|
984 |
|
985 void CTransportFlowShim::IoctlComplete(TDesC8 *aBuf) |
|
986 { |
|
987 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockSSocksspshm, 38)); |
|
988 iSessionControlNotify->IoctlComplete(aBuf); |
|
989 } |
|
990 |
|
991 void CTransportFlowShim::NoBearer(const TDesC8& aConnectionParams) |
|
992 /** |
|
993 Upcall from protocol indicating no underlying bearer for the socket. |
|
994 @param aConnectionParams Additional connection parameters from the stack, in the form of a |
|
995 human readable string. Initially, the required protocols (e.g. "protocol=ip"). |
|
996 */ |
|
997 { |
|
998 // *** NOTE *** |
|
999 // overridden by CUpsTransportFlowShim::NoBearer() for UPS support |
|
1000 |
|
1001 (void)aConnectionParams; |
|
1002 LOG( ESockLog::ConnectionInfoPrintf(aConnectionParams, _L("CTransportFlowShim %08x:\tNoBearer()"), this) ); |
|
1003 |
|
1004 DoNoBearer(); // Do not care if actually posted, so no need to check return value |
|
1005 |
|
1006 } |
|
1007 |
|
1008 void CTransportFlowShim::Bearer(const TDesC8& aConnectionInfo) |
|
1009 { |
|
1010 //we might need to translate the aConnectionInfo into "our" conn info format |
|
1011 LOG( ESockLog::ConnectionInfoPrintf(aConnectionInfo, _L("CTransportFlowShim %08x:\tBearer()"), this) ); |
|
1012 |
|
1013 #if defined(SYMBIAN_TRACE_ENABLE) |
|
1014 const TSoIfConnectionInfo *info = REINTERPRET_CAST(const TSoIfConnectionInfo*, aConnectionInfo.Ptr()); |
|
1015 NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=Bearer(Iap %d, Network %d)"), |
|
1016 this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), info->iIAPId, info->iNetworkId) ) |
|
1017 #endif |
|
1018 |
|
1019 if (TConnectionInfo::IsLocalBearer(aConnectionInfo)) |
|
1020 { |
|
1021 return; |
|
1022 } |
|
1023 |
|
1024 iUseBearerErrors = ETrue; |
|
1025 LocalName(iLocalAddress); |
|
1026 iLocalAddressSet = ETrue; |
|
1027 RemName(iRemoteAddress); |
|
1028 iRemoteAddressSet = ETrue; |
|
1029 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 41)); // legacy flows have no control side; should never get here |
|
1030 |
|
1031 PostDataClientRouted(); |
|
1032 } |
|
1033 |
|
1034 TInt CTransportFlowShim::LockToConnectionInfo() |
|
1035 { |
|
1036 //bind provider with the selected connection |
|
1037 // Note that the following SetOption() can result in an upcall into |
|
1038 // CTransportFlowShim::Bearer() in the same stack frame. |
|
1039 TPckgBuf<TConnectionInfo> info; |
|
1040 if (Control(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), info) == KErrNone) |
|
1041 { |
|
1042 LOG(ESockLog::Printf(_L("CTransportFlowShim %08x:\tLockToConnectionInfo() Iap %d, Network %d"), this, info().iIapId, info().iNetId)); |
|
1043 NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=LockToConnectionInfo(Iap %d, Network %d)"), |
|
1044 this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), info().iIapId, info().iNetId) ) |
|
1045 |
|
1046 TPckg<TSoIfConnectionInfo> ifInfo(iIfInfo); |
|
1047 ifInfo().iIAPId = info().iIapId; |
|
1048 ifInfo().iNetworkId = info().iNetId; |
|
1049 iProvider->SetOption(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), ifInfo); |
|
1050 return KErrNone; |
|
1051 } |
|
1052 else |
|
1053 { |
|
1054 LOG(ESockLog::Printf(_L("CTransportFlowShim %08x:\tLockToConnectionInfo()"), this)); |
|
1055 return KErrNotFound; |
|
1056 } |
|
1057 } |
|
1058 |
|
1059 void CTransportFlowShim::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) |
|
1060 { |
|
1061 if (aMessage.IsMessage<TCFDataClient::TBindTo>() && !NoBearerGuard()) |
|
1062 { |
|
1063 //TODO PROD RZ |
|
1064 //This needs investigating and fixing. There are two cases for why is this needed here: |
|
1065 //(1) Bearer mobility is the only scenario for unsolicited TBindTo |
|
1066 //(hence checking the guard above). CTransportFlowShim cannot just migrate to the new, as the |
|
1067 //socket above it needs to be rebound. mobility_761220: |
|
1068 // (1) opens and starts a connection |
|
1069 // (2) opens a socket against |
|
1070 // (3) sendreceive UDP data and expects (packet colouring) that data to go via IAP4. |
|
1071 // (4) migrates to another bearer (IAP5) |
|
1072 // (5) uses the same socket (without rebinding) to sendreceive data and expects |
|
1073 // the data to go via IAP4 again (despite migrating). |
|
1074 //Talk to Ivan Kelly to find out if this is a requirement on the socket (stays connected |
|
1075 //over the old until rebound) or is this a wrong test case. |
|
1076 //If the former, ipscpr will need changing not to propagate TBindTo to its flows if they |
|
1077 //don't ask. |
|
1078 //(2) Rejoing this flow. During rejoin scenario, it's the new owner obtains its new |
|
1079 //dataclient ('this') before ('this') dataclient knowing. The rejoin procedure is make |
|
1080 //before break, hence it tries to apply the new owner, during which time the new |
|
1081 //owner starts and hence attempts to TBindTo his new child. The child hates it |
|
1082 //as it arrives from an unknown node. The rejoin protocol needs rethinking. |
|
1083 RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(KErrNone).CRef()); |
|
1084 return; |
|
1085 } |
|
1086 CNetworkFlow::ReceivedL(aSender, aRecipient, aMessage); |
|
1087 #ifdef SYMBIAN_NETWORKING_UPS |
|
1088 // Allow derived classes to process received messages. |
|
1089 // |
|
1090 // Rationale for ProcessReceivedL() virtual: |
|
1091 // The existing idiom whereby we call CNetworkFlow::ReceivedL() up front is awkward. |
|
1092 // If we move that call into the derived class, the derived class can do its |
|
1093 // specialised processing and then decide to call this base class method for any |
|
1094 // remaining more general processing. In this case, the ProcessReceivedL() would |
|
1095 // not be required. However, CTransportFlowShim will then become unusable if |
|
1096 // instantiated on its own because the call to CNetworkFlow::ReceivedL() is not present. |
|
1097 TInt ret = ProcessReceivedL(aMessage); |
|
1098 if (ret == KErrNone || ret != KErrNotSupported) |
|
1099 { |
|
1100 return; // PREQ1116 Productisation: RE-WORK ProcessReceivedL(). Perhaps return TBool indicating whether message processed. Leave if a "real" error. Extra arguments? |
|
1101 } |
|
1102 #endif |
|
1103 |
|
1104 if ( aMessage.IsMessage<TEBase::TError>() ) |
|
1105 { |
|
1106 SubConnectionError(static_cast<TEBase::TError&>(aMessage)); |
|
1107 } |
|
1108 else if (aMessage.IsMessage<TEBase::TCancel>()) |
|
1109 { |
|
1110 // TCancel can be received as a result of a Connect() being cancelled on the socket and a |
|
1111 // TBindToComplete() with an error being sent to the PRBindTo activity on our control provider. |
|
1112 } |
|
1113 else if (TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
1114 { |
|
1115 switch (aMessage.MessageId().MessageId()) |
|
1116 { |
|
1117 case TEChild::TDestroy::EId : |
|
1118 Destroy(); |
|
1119 break; |
|
1120 default: |
|
1121 //TODO - logging |
|
1122 //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable())); |
|
1123 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 42)); //For debug configurations |
|
1124 User::Leave(KErrNotSupported); //For release configurations |
|
1125 } |
|
1126 } |
|
1127 else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
1128 { |
|
1129 switch (aMessage.MessageId().MessageId()) |
|
1130 { |
|
1131 case TCFDataClient::TStart::EId : |
|
1132 StartFlowL(aSender); |
|
1133 break; |
|
1134 case TCFDataClient::TStop::EId : |
|
1135 StopFlow(static_cast<TCFDataClient::TStop&>(aMessage)); |
|
1136 break; |
|
1137 case TCFDataClient::TProvisionConfig::EId : |
|
1138 |
|
1139 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1140 //Store the provision config message, |
|
1141 //to store the Provision config message |
|
1142 StoreProvision(static_cast<TCFDataClient::TProvisionConfig&>(aMessage)); |
|
1143 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1144 |
|
1145 break; |
|
1146 case TCFDataClient::TCommitBindTo::EId : |
|
1147 /*TODO RZ PROD- mustn't just ignore TCommitBindTo - must implement*/ |
|
1148 break; |
|
1149 case TCFDataClient::TBindTo::EId : |
|
1150 { |
|
1151 TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage)); |
|
1152 TRAPD(err,BindToL(bindToMsg)); |
|
1153 // Ensure that TBindToComplete message gets sent before TIdle so that it gets to the destination |
|
1154 // before destroy processing. |
|
1155 RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(err).CRef()); |
|
1156 ProcessDCIdleState(); // in case we were waiting to send idle |
|
1157 //If we have received TDataClientStart before (when we did not yet have a bearer), |
|
1158 //we complete the start here as well |
|
1159 if (err != KErrNone) |
|
1160 { |
|
1161 //If we have received TDataClientStart before (when we did not yet have a bearer), |
|
1162 //we complete the start here as well |
|
1163 if (iStartRequest.IsOpen()) |
|
1164 { |
|
1165 CompleteStart(err); |
|
1166 } |
|
1167 iBearerExpected = ETrue; |
|
1168 } |
|
1169 else |
|
1170 { |
|
1171 // If we get a TBindTo message then the TNoBearer request has succeeded |
|
1172 // and we can inform the client. |
|
1173 if (iSessionControlNotify) |
|
1174 { |
|
1175 iSessionControlNotify->SetLocalNameComplete(); |
|
1176 } |
|
1177 } |
|
1178 break; |
|
1179 } |
|
1180 default: |
|
1181 //TODO - logging |
|
1182 //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable())); |
|
1183 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 43)); //For debug configurations |
|
1184 User::Leave(KErrNotSupported); //For release configurations |
|
1185 } |
|
1186 } |
|
1187 else if (TCFFlow::ERealmId == aMessage.MessageId().Realm()) |
|
1188 { |
|
1189 switch (aMessage.MessageId().MessageId()) |
|
1190 { |
|
1191 case TCFFlow::TRejoin::EId : |
|
1192 Rejoin(static_cast<TCFFlow::TRejoin&>(aMessage)); |
|
1193 break; |
|
1194 default: |
|
1195 //TODO - logging |
|
1196 //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable())); |
|
1197 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 44)); //For debug configurations |
|
1198 User::Leave(KErrNotSupported); //For release configurations |
|
1199 } |
|
1200 } |
|
1201 else if (TCFInternalEsock::ERealmId == aMessage.MessageId().Realm()) |
|
1202 { |
|
1203 switch (aMessage.MessageId().MessageId()) |
|
1204 { |
|
1205 case TCFInternalEsock::TFlowProvision::EId : |
|
1206 iFlowParams = (static_cast<TCFInternalEsock::TFlowProvision&>(aMessage)).iFlowParams; |
|
1207 break; |
|
1208 default: |
|
1209 //TODO - logging |
|
1210 //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable())); |
|
1211 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 45)); //For debug configurations |
|
1212 User::Leave(KErrNotSupported); //For release configurations |
|
1213 } |
|
1214 } |
|
1215 |
|
1216 //This is the case of Modulation change for a bearer. |
|
1217 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1218 else if (TCFMessage::ERealmId == aMessage.MessageId().Realm()) |
|
1219 { |
|
1220 switch (aMessage.MessageId().MessageId()) |
|
1221 { |
|
1222 case TCFMessage::TTransportNotification::EId : |
|
1223 //In case of modulation change, |
|
1224 //extract the value from this message, |
|
1225 //pass it to the shim to set the options for socket. |
|
1226 SetProtocolOptions(); |
|
1227 break; |
|
1228 default: |
|
1229 //TODO : Logging for error message |
|
1230 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 46)); //For debug configurations |
|
1231 User::Leave(KErrNotSupported); //For release configurations |
|
1232 } |
|
1233 } |
|
1234 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1235 |
|
1236 else if ( aMessage.IsMessage<TCFPeer::TJoinComplete>() ) |
|
1237 {;} |
|
1238 else if ( aMessage.IsMessage<TCFControlProvider::TBearer>() ) |
|
1239 { |
|
1240 //If we have received TDataClientStart before (when we did not yet have a bearer), |
|
1241 //we complete the start here as well |
|
1242 if (iStartRequest.IsOpen()) |
|
1243 { |
|
1244 CompleteStart(KErrNone); |
|
1245 } |
|
1246 LOG( ESockLog::Printf(_L8("CTransportFlowShim %08x:\tReceivedL(): TBearer: iDeleteUponBearerReception %d"), this, iDeleteUponBearerReception) ); |
|
1247 |
|
1248 ClearNoBearerGuard(); |
|
1249 ProcessDCIdleState(); |
|
1250 NoBearerCompletion(); // may delete this ! |
|
1251 } |
|
1252 else |
|
1253 { |
|
1254 //TODO - logging |
|
1255 //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable())); |
|
1256 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksspshm, 47)); //For debug configurations |
|
1257 User::Leave(KErrNotSupported); //For release configurations |
|
1258 } |
|
1259 } |
|
1260 |
|
1261 void CTransportFlowShim::NoBearerCompletion() |
|
1262 { |
|
1263 iBearerExpected = EFalse; |
|
1264 if (iDeleteUponBearerReception) |
|
1265 { |
|
1266 delete this; |
|
1267 } |
|
1268 } |
|
1269 |
|
1270 const TNodeId& CTransportFlowShim::NodeId() const |
|
1271 { |
|
1272 return Id(); |
|
1273 } |
|
1274 |
|
1275 void CTransportFlowShim::CompleteStart(TInt aError) |
|
1276 { |
|
1277 if (aError==KErrNone) |
|
1278 { |
|
1279 iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef()); |
|
1280 iIsStarted = ETrue; |
|
1281 iIsStopped = EFalse; |
|
1282 } |
|
1283 else |
|
1284 { |
|
1285 iStartRequest.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(),aError).CRef()); |
|
1286 } |
|
1287 iStartRequest.Close(); |
|
1288 } |
|
1289 |
|
1290 void CTransportFlowShim::SubConnectionError(const TEBase::TError& errorMsg, TUint anOperationMask) |
|
1291 { |
|
1292 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() errorMsg.iValue %d, anOperationMask %d"), this, errorMsg.iValue, anOperationMask) ); |
|
1293 |
|
1294 if (errorMsg.iMsgId == TCFControlProvider::TNoBearer::Id()) |
|
1295 { |
|
1296 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - clearing no-bearer guard"), this) ); |
|
1297 ClearNoBearerGuard(); |
|
1298 #ifdef SYMBIAN_NETWORKING_UPS |
|
1299 ProcessDCIdleState(); |
|
1300 #endif |
|
1301 NoBearerCompletion(); |
|
1302 } |
|
1303 |
|
1304 if (IsBoundToSession()) |
|
1305 { |
|
1306 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - calling Error() function"), this) ); |
|
1307 Error(errorMsg.iValue, anOperationMask); |
|
1308 } |
|
1309 else if (iHostResolverNotify) |
|
1310 { |
|
1311 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tSubConnectionError() - passing to host resolver's Error() function"), this) ); |
|
1312 iHostResolverNotify->Error(errorMsg.iValue); |
|
1313 } |
|
1314 } |
|
1315 |
|
1316 void CTransportFlowShim::BindToL(TCFDataClient::TBindTo& aBindTo) |
|
1317 /** |
|
1318 Request from control side (at network layer) to indicate that the SubConnection is |
|
1319 up and running and that we should bind to a Flow below. |
|
1320 |
|
1321 @param aLowerFlow Flow below to bind to. |
|
1322 */ |
|
1323 { |
|
1324 //provisioning message must come before bindto in case we didn't get it after we've joined |
|
1325 //the sub-connection |
|
1326 |
|
1327 NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"), |
|
1328 this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) ) |
|
1329 |
|
1330 if (iShuttingDown) |
|
1331 { |
|
1332 User::Leave(KErrCancel); |
|
1333 return; |
|
1334 } |
|
1335 |
|
1336 CNetworkFlow::BindToL(aBindTo); |
|
1337 if (iLowerFlow && IsBoundToSession()) |
|
1338 { |
|
1339 LockToConnectionInfo(); |
|
1340 LocalName(iLocalAddress); |
|
1341 iLocalAddressSet = ETrue; |
|
1342 RemName(iRemoteAddress); |
|
1343 iRemoteAddressSet = ETrue; |
|
1344 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 48)); // legacy flows have no control side; should never get here |
|
1345 } |
|
1346 else if (iHostResolverNotify) |
|
1347 {//workaroud to indicate to CHostResolver we've got connection info |
|
1348 if (aBindTo.iNodeId.Ptr()) |
|
1349 { |
|
1350 iHostResolverNotify->StartSending(); |
|
1351 } |
|
1352 else |
|
1353 { |
|
1354 iHostResolverNotify->Error(KErrDisconnected); |
|
1355 } |
|
1356 } |
|
1357 |
|
1358 |
|
1359 |
|
1360 } |
|
1361 |
|
1362 |
|
1363 void CTransportFlowShim::Rejoin(const TCFFlow::TRejoin& aRejoinMessage) |
|
1364 { |
|
1365 LOG( ESockLog::Printf(_L("CTransportFlowShim %08x:\tRejoin()"), this )); |
|
1366 iSubConnectionProvider.Close(); |
|
1367 iSubConnectionProvider.Open(TNodeCtxId(0, aRejoinMessage.iNodeId)); |
|
1368 //If already bound there's a potential need to rebind. |
|
1369 //As the new control provider for the flow - if different than |
|
1370 //the current, rebind. |
|
1371 if (iLowerFlow) |
|
1372 { |
|
1373 PostNoBearer(); |
|
1374 } |
|
1375 } |
|
1376 |
|
1377 void CTransportFlowShim::StartFlowL(const TRuntimeCtxId& aSender) |
|
1378 { |
|
1379 __ASSERT_DEBUG(!iIsStarted, User::Panic(KSpecAssert_ESockSSocksspshm, 49)); |
|
1380 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 50)); // legacy flows have no control side; should never get here |
|
1381 |
|
1382 //We will wait for it and complete the start after we have received it |
|
1383 User::LeaveIfError(iStartRequest.Open(iSubConnectionProvider, aSender)); |
|
1384 |
|
1385 if (iDCIdle != EClientsPresent) |
|
1386 { |
|
1387 iStartRequest.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(), KErrNotReady).CRef()); |
|
1388 iStartRequest.Close(); |
|
1389 return; |
|
1390 } |
|
1391 |
|
1392 if (iLowerFlow) |
|
1393 { |
|
1394 iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef()); |
|
1395 iStartRequest.Close(); |
|
1396 iIsStarted = ETrue; |
|
1397 iIsStopped = EFalse; |
|
1398 return; |
|
1399 } |
|
1400 |
|
1401 //We need a bearer |
|
1402 PostNoBearer(); //Ask for bearer if not requested already |
|
1403 |
|
1404 } |
|
1405 |
|
1406 void CTransportFlowShim::StopFlow(TCFDataClient::TStop& aMessage) |
|
1407 { |
|
1408 __ASSERT_DEBUG(iIsStarted, User::Panic(KSpecAssert_ESockSSocksspshm, 51)); //Must be started now |
|
1409 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 52)); // legacy flows have no control side; should never get here |
|
1410 |
|
1411 // We need to error the socket if the lower protocol stack is not going to do this. Once a |
|
1412 // Bearer() upcall has been received, the lower protocol will call Error() if the connection |
|
1413 // goes down. Before this point, the lower protocol will not call Error(), so StopFlow() calls |
|
1414 // from the SCPR are used to error the socket (if the interface start fails). |
|
1415 // |
|
1416 // The main scenario is the TCP/IP stack as lower protocol which will only call Error() once it |
|
1417 // has attached a flow to a route (and hence an interface) which, in turn, only occurs once the |
|
1418 // interface is up and data has been sent over the socket. Note that opening an RSocket on an |
|
1419 // RConnection but not transferring any data will not cause the TCP/IP stack to attach the flow |
|
1420 // to the route and hence not call Error() if the interface comes down. |
|
1421 |
|
1422 if (IsBoundToSession() && !iUseBearerErrors) |
|
1423 { |
|
1424 Error(aMessage.iValue, EErrorAllOperations); |
|
1425 } |
|
1426 |
|
1427 if (iLowerFlow) |
|
1428 { |
|
1429 iLowerFlow->Unbind(NULL,NULL); |
|
1430 iLowerFlow = NULL; |
|
1431 } |
|
1432 iLowerControl = NULL; |
|
1433 |
|
1434 iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(aMessage.iValue).CRef()); |
|
1435 iIsStarted = EFalse; |
|
1436 iIsStopped = ETrue; |
|
1437 } |
|
1438 |
|
1439 void CTransportFlowShim::InitDestroy() |
|
1440 { |
|
1441 __ASSERT_DEBUG(iDCIdle <= EClientsPresent, User::Panic(KSpecAssert_ESockSSocksspshm, 53)); |
|
1442 iDCIdle = EIdle; |
|
1443 |
|
1444 if(iSubConnectionProvider.IsOpen()) // legacy flows have no control side |
|
1445 { |
|
1446 ProcessDCIdleState(); |
|
1447 } |
|
1448 else |
|
1449 { |
|
1450 DeleteThisFlow(); |
|
1451 } |
|
1452 } |
|
1453 |
|
1454 void CTransportFlowShim::Destroy() |
|
1455 { |
|
1456 DeleteThisFlow(); |
|
1457 } |
|
1458 |
|
1459 void CTransportFlowShim::PostNoBearer() |
|
1460 { |
|
1461 if (!NoBearerGuard()) |
|
1462 { |
|
1463 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TNoBearer().CRef()); |
|
1464 SetNoBearerGuard(); |
|
1465 } |
|
1466 } |
|
1467 |
|
1468 void CTransportFlowShim::PostDataClientRouted() |
|
1469 { |
|
1470 if (iLocalAddressSet && iRemoteAddressSet |
|
1471 && iRemoteAddress.Family() != KAFUnspec && !iDataClientRoutedGuard) |
|
1472 { |
|
1473 iSubConnectionProvider.PostMessage( |
|
1474 Id(), |
|
1475 TCFIPMessages::TDataClientRouted( |
|
1476 TAddrUpdate( |
|
1477 iLocalAddress, |
|
1478 iRemoteAddress, |
|
1479 iFlowParams.iProtocol, |
|
1480 iIfInfo.iIAPId) |
|
1481 ).CRef() |
|
1482 ); |
|
1483 iDataClientRoutedGuard = ETrue; |
|
1484 } |
|
1485 } |
|
1486 |
|
1487 void CTransportFlowShim::ClearDataClientRoutedGuard() |
|
1488 { |
|
1489 iDataClientRoutedGuard = EFalse; |
|
1490 } |
|
1491 |
|
1492 |
|
1493 /* |
|
1494 Store the provision information passed from the Control side. |
|
1495 @param TProvisionConfig Message recd. |
|
1496 */ |
|
1497 void CTransportFlowShim::StoreProvision(TCFDataClient::TProvisionConfig& aMessage) |
|
1498 { |
|
1499 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1500 //find access point inforamtion from the message |
|
1501 iAccessPointConfig.Close(); |
|
1502 iAccessPointConfig.Open(aMessage.iConfig); |
|
1503 //Find extension appended at NetMcpr and store it |
|
1504 //Presently will extract CSAPSetOpt window extensions |
|
1505 ExtractSetOptExtensions(); |
|
1506 #else |
|
1507 (void)aMessage; |
|
1508 #endif |
|
1509 } |
|
1510 /* |
|
1511 Extract extensions appended to TProvisionConfig specific to IPTransport. |
|
1512 */ |
|
1513 void CTransportFlowShim::ExtractSetOptExtensions() |
|
1514 { |
|
1515 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
1516 //Extract TCP receive window specific provisionconfig extension. |
|
1517 iProtocolOptions = static_cast< const CSAPSetOpt*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CSAPSetOpt::EUid,CSAPSetOpt::ETypeId))); |
|
1518 #endif |
|
1519 } |
|
1520 |
|
1521 #ifdef SYMBIAN_NETWORKING_UPS |
|
1522 |
|
1523 TBool CTransportFlowShim::ActivityRunning() |
|
1524 /** |
|
1525 Determine whether we are in the middle of a NoBearer activity. |
|
1526 |
|
1527 In other words, we are waiting for a response from a previously transmitted TNoBearer. |
|
1528 |
|
1529 @return ETrue if in the middle of one of this activity, else EFalse. |
|
1530 */ |
|
1531 { |
|
1532 return NoBearerGuard(); |
|
1533 } |
|
1534 |
|
1535 // |
|
1536 // Default implementations of CTransportFlowShim virtuals. |
|
1537 // |
|
1538 |
|
1539 TInt CTransportFlowShim::SetupForNoBearerOnSend() |
|
1540 { |
|
1541 return KErrNotSupported; |
|
1542 } |
|
1543 |
|
1544 void CTransportFlowShim::PreUnbind() |
|
1545 { |
|
1546 } |
|
1547 |
|
1548 TInt CTransportFlowShim::ProcessReceivedL(TSignatureBase& /*aCFMessage*/) |
|
1549 { |
|
1550 return KErrNotSupported; |
|
1551 } |
|
1552 |
|
1553 // |
|
1554 // CUpsTransportFlowShim methods |
|
1555 // |
|
1556 // This class contains User Prompt Service (UPS) specific functionality. |
|
1557 // |
|
1558 |
|
1559 CUpsTransportFlowShim* CUpsTransportFlowShim::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
1560 /** |
|
1561 Create a new CUpsTransportFlowShim instanace. |
|
1562 |
|
1563 Note: this method replaces CTransportFlowShim::NewL() in UPS builds. |
|
1564 */ |
|
1565 { |
|
1566 return new (ELeave) CUpsTransportFlowShim(aFactory, aSubConn, aProtocolIntf); |
|
1567 } |
|
1568 |
|
1569 TInt CUpsTransportFlowShim::SetupForNoBearerOnSend() |
|
1570 /** |
|
1571 Called just before a TNoBearer message is posted for Host Resolver processing. |
|
1572 |
|
1573 Perform the Platform Security capability check and populate the UPS Access Point Config (APC) extension. |
|
1574 |
|
1575 @return KErrNone or a system wide error code. |
|
1576 */ |
|
1577 { |
|
1578 // For UPS, the capability check has been moved from the provider SAP to here so that |
|
1579 // the capability check result is available at the time of the NoBearer message being sent. |
|
1580 __ASSERT_DEBUG(iSecurityChecker, User::Panic(KSpecAssert_ESockSSocksspshm, 54)); |
|
1581 TInt result = iSecurityChecker->CheckPolicy(KPolicyNetworkServices, "UpsTransportFlowShim (SetupForNoBearerOnSend)"); |
|
1582 |
|
1583 // At this point, result can contain: |
|
1584 // |
|
1585 // KErrNone Capability check passed. |
|
1586 // KErrPermissionDenied Capability check failed. |
|
1587 // KErrCompletion Special error code that instructs us not to perform any UPS check. |
|
1588 // This is a means for upper layers to disable UPS checking in circumstances |
|
1589 // where the UPS check will be catered for by a higher layer. |
|
1590 if (result != KErrCompletion) |
|
1591 { |
|
1592 if (UpsEnabled()) |
|
1593 { |
|
1594 // UPS enabled - fill in the APC structure associated with TNoBearer message |
|
1595 PopulateUpsExtension(result); |
|
1596 } |
|
1597 else |
|
1598 { |
|
1599 // UPS disabled - fall back to the Platform Security check |
|
1600 if (result != KErrNone) |
|
1601 { |
|
1602 return TSendResult(result); |
|
1603 } |
|
1604 } |
|
1605 } |
|
1606 return KErrNone; |
|
1607 } |
|
1608 |
|
1609 void CUpsTransportFlowShim::PreUnbind() |
|
1610 /** |
|
1611 Called just before an unbind happens. |
|
1612 |
|
1613 Ensure that we cancel any running activities. |
|
1614 |
|
1615 (there are no activities on the data side in the formal sense - the term is used |
|
1616 to describe NoBearer processing happening locally). |
|
1617 */ |
|
1618 { |
|
1619 if (ActivityRunning()) |
|
1620 { |
|
1621 // @TODO PREQ1116 - should we be able to have a NoBearer and a PolicyCheckRequest pending |
|
1622 // at the same time ? Should we prevent it? |
|
1623 |
|
1624 // Cancel any pending NoBearer activity. This has become necessary because the UPS authorisation |
|
1625 // can cause the NoBearer activity to be pending for an indefinate period of time. When the |
|
1626 // cancel reaches the MCpr, the UPS authorisation will be cancelled and a TError will eventually |
|
1627 // be received and processed in SubConnectionError(). |
|
1628 iSubConnectionProvider.PostMessage(Id(), Messages::TEBase::TCancel().CRef()); |
|
1629 } |
|
1630 } |
|
1631 |
|
1632 TInt CUpsTransportFlowShim::SetOption(TUint aLevel, TUint aName, const TDesC8 &anOption) |
|
1633 /** |
|
1634 Process SetOption() requests from upper layer |
|
1635 */ |
|
1636 { |
|
1637 if (aLevel == KSOLProvider) |
|
1638 { |
|
1639 if (aName == KSoOwnerInfo) |
|
1640 { |
|
1641 // Upper layer communicating process and thread id of client opening subsession. |
|
1642 __ASSERT_DEBUG(anOption.Size() == sizeof(TSoOwnerInfo), User::Panic(KSpecAssert_ESockSSocksspshm, 55)); |
|
1643 |
|
1644 const TSoOwnerInfo* soOwnerInfoPtr = reinterpret_cast <const TSoOwnerInfo*> (anOption.Ptr()); |
|
1645 __ASSERT_DEBUG(soOwnerInfoPtr, User::Panic(KSpecAssert_ESockSSocksspshm, 56)); |
|
1646 |
|
1647 iThreadId = soOwnerInfoPtr->iThreadId; |
|
1648 iProcessId = soOwnerInfoPtr->iProcessId; |
|
1649 } |
|
1650 else |
|
1651 if (aName == KSoSetPlatSecApi) |
|
1652 { |
|
1653 // Upper layer communicating an 'M' class instance that can be used for retrieving |
|
1654 // process and thread id of client performing current operation. |
|
1655 __ASSERT_DEBUG(anOption.Size() == sizeof(const MPlatsecApiExt*), User::Panic(KSpecAssert_ESockSSocksspshm, 57)); |
|
1656 iPlatsecIf = *reinterpret_cast <const MPlatsecApiExt* const *> (anOption.Ptr()); |
|
1657 } |
|
1658 |
|
1659 if (IsHostResolver()) |
|
1660 { |
|
1661 // For Host Resolvers, the SetOption() is only for us to store the thread and process id, |
|
1662 // so we are complete. There is no iProvider in this case to propagate the call to. |
|
1663 __ASSERT_DEBUG(Provider() == NULL, User::Panic(KSpecAssert_ESockSSocksspshm, 58)); |
|
1664 return KErrNone; |
|
1665 } |
|
1666 } |
|
1667 |
|
1668 return CTransportFlowShim::SetOption(aLevel, aName, anOption); |
|
1669 } |
|
1670 |
|
1671 TInt CUpsTransportFlowShim::SecurityCheck(MProvdSecurityChecker* aChecker) |
|
1672 /** |
|
1673 Called from upper layer to ask the SAP provider to perform a security policy check |
|
1674 on the client process. |
|
1675 |
|
1676 @param aChecker Security checker class instance |
|
1677 @return KErrNone or a system wide error code |
|
1678 */ |
|
1679 { |
|
1680 // Save away the security checker class so that we can perform capability checking |
|
1681 // here instead of in the TCP/IP stack. |
|
1682 // |
|
1683 // Note: iSecurityChecker can get overwritten as a result of ProtocolManager::TransferSocketL(), |
|
1684 // so don't ASSERT(iSecurityChecker == NULL). |
|
1685 iSecurityChecker = aChecker; |
|
1686 |
|
1687 if (Provider()) |
|
1688 { |
|
1689 // Sockets |
|
1690 __ASSERT_DEBUG(!IsHostResolver(), User::Panic(KSpecAssert_ESockSSocksspshm, 59)); |
|
1691 return Provider()->SecurityCheck(aChecker); |
|
1692 } |
|
1693 else |
|
1694 { |
|
1695 // Host Resolvers |
|
1696 __ASSERT_DEBUG(IsHostResolver(), User::Panic(KSpecAssert_ESockSSocksspshm, 60)); |
|
1697 return KErrNone; |
|
1698 } |
|
1699 } |
|
1700 |
|
1701 void CUpsTransportFlowShim::GetProcessAndThreadId(TProcessId& aProcessId, TThreadId& aThreadId) const |
|
1702 /** |
|
1703 Retrieve the process and thread id corresponding to the current Socket/Host Resolver request. |
|
1704 |
|
1705 The iProcessId and iThreadId variables contain the ids at the time of subsession open, which |
|
1706 is not necessarily the same as the ids of the client performing the actual request. The |
|
1707 call to iPlatsecIf->GetProcessAndThreadId() will actually go to the layer above for processing |
|
1708 and retrieve the ids associated with the current pending request. |
|
1709 |
|
1710 @param aProcessId variable receiving process id (out) |
|
1711 @param aThreadId variable receiveing thread id (out) |
|
1712 @return KErrNone, else a system wide error code. |
|
1713 */ |
|
1714 { |
|
1715 TInt err = KErrGeneral; |
|
1716 if (iPlatsecIf) |
|
1717 { |
|
1718 err = iPlatsecIf->GetProcessAndThreadId(aProcessId, aThreadId); |
|
1719 } |
|
1720 |
|
1721 if (err != KErrNone) |
|
1722 { |
|
1723 aProcessId = iProcessId; |
|
1724 aThreadId = iThreadId; |
|
1725 } |
|
1726 } |
|
1727 |
|
1728 void CUpsTransportFlowShim::NoBearer(const TDesC8& aConnectionParams) |
|
1729 /** |
|
1730 Upcall from protocol indicating no underlying bearer for the socket. |
|
1731 @param aConnectionParams Additional connection parameters from the stack, in the form of a |
|
1732 human readable string. Initially, the required protocols (e.g. "protocol=ip"). |
|
1733 |
|
1734 This method overrides CTransportFlowShim::NoBearer() for UPS specific handling. |
|
1735 */ |
|
1736 { |
|
1737 (void)aConnectionParams; |
|
1738 LOG( ESockLog::Printf(_L8("CUpsTransportFlowShim %08x:\tNoBearer(%S)"), this, &aConnectionParams) ); |
|
1739 |
|
1740 // Perform the Platform Security check (moved from the Provider SAP to here in order to |
|
1741 // obtain the platsec result as part of UPS processing). |
|
1742 |
|
1743 TInt result = iSecurityChecker->CheckPolicy(KPolicyNetworkServices, "TransportFlowShim (NoBearer)"); |
|
1744 |
|
1745 NM_LOG((KESockServerTag, _L8("CTransportFlowShim %08x:\tSynchronous call: From=%08x To=%08x Func=NoBearer(%S)"), |
|
1746 this, static_cast<Messages::ANode*>(this), static_cast<Messages::ANode*>(this), &aConnectionParams) ) |
|
1747 |
|
1748 // At this point, result can contain: |
|
1749 // |
|
1750 // KErrNone Capability check passed. |
|
1751 // KErrPermissionDenied Capability check failed. |
|
1752 // KErrCompletion Special error code that instructs us not to perform any UPS check. |
|
1753 // This is a means for upper layers to disable UPS checking in circumstances |
|
1754 // where the UPS check will be catered for by a higher layer. |
|
1755 |
|
1756 TBool disableUpsCheck = (result == KErrCompletion); |
|
1757 if (!disableUpsCheck && !UpsEnabled()) |
|
1758 { |
|
1759 // UPS disabled - fall back to the Platform Security check |
|
1760 if (result != KErrNone) |
|
1761 { |
|
1762 Error(result, MSocketNotify::EErrorSend | MSocketNotify::EErrorConnect); |
|
1763 return; |
|
1764 } |
|
1765 } |
|
1766 |
|
1767 if(!IsStopped()) |
|
1768 { // Prevent sending NoBearer if DataClientStop was received |
|
1769 ParseNoBearerParams(aConnectionParams); |
|
1770 if (iIsScoped) |
|
1771 { |
|
1772 if (!disableUpsCheck && UpsEnabled()) |
|
1773 { |
|
1774 // Do not perform standard NoBearer() processing for "gratuitous" NoBearer() calls. The |
|
1775 // TCP/IP stack already has enough scope information to select an interface, but this |
|
1776 // probably will be different from the "default" implicit interface that the control side will |
|
1777 // select. The consequence is that the TransportFlowShim could end up being associated with the |
|
1778 // wrong SCpr. Note that this is not a problem introduced by UPS functionality - it exists in |
|
1779 // the Networking Subsystem anyway. The "Bearer()-only" cases in pre-UPS code do not result in |
|
1780 // the TCP/IP stack generating a NoBearer() (just a Bearer()), so the TransportFlowShim never |
|
1781 // gets associated with any SCpr. We are just replicating this behaviour for UPS functionality, |
|
1782 // by performing a TPolicyCheckRequest sequence for the sake of UPS checking, but otherwise the |
|
1783 // behaviour mirrors what is already present (i.e. does nothing else). |
|
1784 PostPolicyCheckRequest(result); |
|
1785 } |
|
1786 else |
|
1787 { |
|
1788 // If no UPS handling is required, tell the TCP/IP stack that it can go ahead and route the flow. |
|
1789 IssueScopedNoBearerResponse(); |
|
1790 } |
|
1791 } |
|
1792 else |
|
1793 if (LockToConnectionInfo() != KErrNone) |
|
1794 { |
|
1795 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockSSocksspshm, 61)); // legacy flows have no control side; should never get here |
|
1796 // If UPS is enabled, fill in the APC structure to accompany the TNoBearer |
|
1797 // Do this even if disableUpsCheck is set so that the APC will contain KErrCompletion. |
|
1798 if (UpsEnabled()) |
|
1799 { |
|
1800 PopulateUpsExtension(result); |
|
1801 } |
|
1802 PostNoBearer(); |
|
1803 } |
|
1804 ClearUseBearerErrors(); |
|
1805 ClearDataClientRoutedGuard(); |
|
1806 } |
|
1807 else |
|
1808 { |
|
1809 // Return an error on an attempt to issue a SendTo() on an explicit socket (datagram) whose corresponding |
|
1810 // connection has gone down (BR2639). Note that the use of KErrDisconnected should NOT be documented - |
|
1811 // in future, we may wish to return the same error as the connection itself experienced. |
|
1812 Error(KErrDisconnected, MSessionControlNotify::EErrorSend); |
|
1813 } |
|
1814 } |
|
1815 |
|
1816 void CUpsTransportFlowShim::PopulateUpsExtension(TInt aPolicyCheckResult) const |
|
1817 /** |
|
1818 Populate the UPS Access Point Config structure with the required information in preparation for |
|
1819 a TNoBearer message to be transmitted. |
|
1820 |
|
1821 @param aPolicyCheckResult result of Platform Security check |
|
1822 */ |
|
1823 { |
|
1824 __ASSERT_DEBUG(iUpsExtension, User::Panic(KSpecAssert_ESockSSocksspshm, 62)); |
|
1825 iUpsExtension->SetPolicyCheckResult(aPolicyCheckResult); |
|
1826 |
|
1827 TProcessId processId; |
|
1828 TThreadId threadId; |
|
1829 GetProcessAndThreadId(processId, threadId); |
|
1830 |
|
1831 iUpsExtension->SetProcessId(processId); |
|
1832 iUpsExtension->SetThreadId(threadId); |
|
1833 |
|
1834 if (IsHostResolver()) |
|
1835 { |
|
1836 // Null destination name for Host Resolvers. |
|
1837 iUpsExtension->ResetDestinationAddr(); |
|
1838 iUpsExtension->SetDestinationAddrType(ETNone); |
|
1839 } |
|
1840 else |
|
1841 { |
|
1842 // @TODO PREQ1116 - something better than this cast? For example, argument to |
|
1843 // SetDestinationAddr() could become a "const TDesC8&" perhaps (without worrying about |
|
1844 // error checking) ? |
|
1845 iUpsExtension->SetDestinationAddr(static_cast<TUpsDestinationAddr>(iRemoteAddress)); |
|
1846 iUpsExtension->SetDestinationAddrType(ETSockAddress); |
|
1847 } |
|
1848 } |
|
1849 |
|
1850 |
|
1851 void CUpsTransportFlowShim::PostPolicyCheckRequest(TInt aPolicyCheckResult) |
|
1852 /** |
|
1853 Post a TPolicyCheckRequest message to the SCpr |
|
1854 |
|
1855 @param aPolicyCheckResult result of Platform Security check |
|
1856 */ |
|
1857 { |
|
1858 if (!PolicyCheckRequestPending()) |
|
1859 { |
|
1860 __ASSERT_DEBUG(UpsEnabled(), User::Panic(KSpecAssert_ESockSSocksspshm, 63)); // UPS should not be "short circuited" off |
|
1861 |
|
1862 TProcessId processId; |
|
1863 TThreadId threadId; |
|
1864 GetProcessAndThreadId(processId, threadId); |
|
1865 |
|
1866 const TPolicyCheckRequestParams params(processId, threadId, aPolicyCheckResult, static_cast<TUpsDestinationAddr>(iRemoteAddress), ETSockAddress); |
|
1867 iSubConnectionProvider.PostMessage(Id(), UpsMessage::TPolicyCheckRequest(params).CRef()); |
|
1868 SetPolicyCheckRequestPending(ETrue); |
|
1869 } |
|
1870 } |
|
1871 |
|
1872 void CUpsTransportFlowShim::ProcessPolicyCheckResponse(const UpsMessage::TPolicyCheckResponse& aResponse) |
|
1873 /** |
|
1874 Process a TPolicyCheckResponse from the SCpr. |
|
1875 |
|
1876 If UPS authorisation was granted, prod the TCP/IP stack into re-attaching the flow (based on the original |
|
1877 scope id in the socket address). |
|
1878 |
|
1879 @param aResponse TPolicyCheckResponse message |
|
1880 */ |
|
1881 { |
|
1882 SetPolicyCheckRequestPending(EFalse); |
|
1883 |
|
1884 if (iDCIdle == EIdle) |
|
1885 { |
|
1886 ProcessDCIdleState(); |
|
1887 } |
|
1888 else |
|
1889 { |
|
1890 if (aResponse.iValue == KErrNone) |
|
1891 { |
|
1892 if (iIsScoped) |
|
1893 { |
|
1894 // If socket address already has a scope id, do not tell the stack to use our |
|
1895 // idea of NetworkId. If we do, our idea of the NetworkId could be a mismatch |
|
1896 // with the existing scope id, and we could end up with an SCPR which represents a |
|
1897 // different interface from the one that the TCP/IP stack has chosen based on the scope |
|
1898 // id. Use the special KNetworkIdFromAddress value for NetworkId which the TCP/IP stack |
|
1899 // recognises as meaning "attempt to attach the flow to a route, but determine the |
|
1900 // NetworkId from the socket address, as you've already indicated in the NoBearer() |
|
1901 // that you have enough information to do so". |
|
1902 // |
|
1903 // This code has become necessary due to the UPS support, which forces the |
|
1904 // TCP/IP stack to issue NoBearer() calls in circumstances where it never used to |
|
1905 // before, to give an opportunity to perform UPS authorisation. |
|
1906 IssueScopedNoBearerResponse(); |
|
1907 } |
|
1908 } |
|
1909 else |
|
1910 { |
|
1911 Error(aResponse.iValue, MSocketNotify::EErrorSend | MSocketNotify::EErrorConnect); |
|
1912 } |
|
1913 } |
|
1914 } |
|
1915 |
|
1916 void CUpsTransportFlowShim::IssueScopedNoBearerResponse() |
|
1917 /** |
|
1918 After a gratuitous NoBearer() upcall has been issued to us (to allow a chance for UPS checking to occur before |
|
1919 a flow is routed), issue the response to the TCP/IP stack indicating that it can now route the flow and continue. |
|
1920 */ |
|
1921 { |
|
1922 TSoIfConnectionInfo info; |
|
1923 TPckg<TSoIfConnectionInfo> ifInfo(info); |
|
1924 info.iIAPId = 0; |
|
1925 info.iNetworkId = KNetworkIdFromAddress; |
|
1926 __ASSERT_DEBUG(Provider(), User::Panic(KSpecAssert_ESockSSocksspshm, 64)); |
|
1927 SetIfInfo(info); |
|
1928 Provider()->SetOption(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), ifInfo); |
|
1929 } |
|
1930 |
|
1931 void CUpsTransportFlowShim::ParseNoBearerParams(const TDesC8& aConnectionParams) |
|
1932 /** |
|
1933 Parse the descriptor passed in NoBearer() upcall. |
|
1934 |
|
1935 Main raison d'etre for this routine is to check whether the "scoped" string was |
|
1936 part of the descriptor contents (indicating a "gratuitous" NoBearer()). |
|
1937 |
|
1938 @param aConnectionParams Argument passed in NoBearer() upcall from lower layer. |
|
1939 */ |
|
1940 { |
|
1941 _LIT8(KScoped, "scoped"); |
|
1942 if (aConnectionParams.Find(KScoped()) != KErrNotFound) |
|
1943 { |
|
1944 // "scoped" string signifies a "gratuitous" NoBearer(). The flow could have been routed |
|
1945 // without a NoBearer() (i.e. it was scoped enough to route it), but the NoBearer() was |
|
1946 // generated anyway so that ESock could perform UPS checking before routing it. |
|
1947 iIsScoped = ETrue; |
|
1948 } |
|
1949 else |
|
1950 { |
|
1951 iIsScoped = EFalse; |
|
1952 } |
|
1953 } |
|
1954 |
|
1955 TInt CUpsTransportFlowShim::ProcessReceivedL(TSignatureBase& aCFMessage) |
|
1956 /* |
|
1957 Process any SCpr messages specific to UPS functionality. |
|
1958 |
|
1959 Called from base class (CTransportFlowShim) before it attempts to process the incoming message. |
|
1960 |
|
1961 @param aCFMessage Message from SCpr |
|
1962 @return KErrNone if we have handled the incoming message and no more processing is necessary, |
|
1963 KErrNotSupported if have not handled the incoming message, else a system wide error code. |
|
1964 */ |
|
1965 { |
|
1966 // Check for special UPS messages. |
|
1967 if (UpsMessage::ERealmId == aCFMessage.MessageId().Realm()) |
|
1968 { |
|
1969 switch (aCFMessage.MessageId().MessageId()) |
|
1970 { |
|
1971 case UpsMessage::TPolicyCheckResponse::EId : |
|
1972 { |
|
1973 // Support for UPS |
|
1974 const UpsMessage::TPolicyCheckResponse& policyCheckResponseMsg = static_cast<UpsMessage::TPolicyCheckResponse&>(aCFMessage); |
|
1975 ProcessPolicyCheckResponse(policyCheckResponseMsg); |
|
1976 return KErrNone; |
|
1977 } |
|
1978 } |
|
1979 } |
|
1980 else |
|
1981 if (TCFDataClient::ERealmId == aCFMessage.MessageId().Realm()) |
|
1982 { |
|
1983 switch (aCFMessage.MessageId().MessageId()) |
|
1984 { |
|
1985 case TCFDataClient::TProvisionConfig::EId : |
|
1986 { |
|
1987 // Get a pointer to the UPS Access Point Config structure. If not present, then UPS is |
|
1988 // disabled ("short circuited") and iUpsExtension remains set to NULL. |
|
1989 const TCFDataClient::TProvisionConfig& provisionMsg = static_cast<TCFDataClient::TProvisionConfig&>(aCFMessage); |
|
1990 |
|
1991 iAccessPointConfig.Close(); |
|
1992 iAccessPointConfig.Open(provisionMsg.iConfig); |
|
1993 |
|
1994 const Meta::SMetaData* const extension = AccessPointConfig().FindExtension( |
|
1995 STypeId::CreateSTypeId(CUPSAccessPointConfigExt::EUPSAccessPointConfigUid, CUPSAccessPointConfigExt::ETypeId)); |
|
1996 if (extension) |
|
1997 { |
|
1998 iUpsExtension = const_cast<CUPSAccessPointConfigExt*> (static_cast<const CUPSAccessPointConfigExt*>(extension)); |
|
1999 } |
|
2000 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
2001 // |
|
2002 //Store the provision config message, |
|
2003 //to store the Provision config message |
|
2004 //which will have TCP Receive window sizes. |
|
2005 StoreProvision(static_cast<TCFDataClient::TProvisionConfig&>(aCFMessage)); |
|
2006 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
2007 |
|
2008 return KErrNone; |
|
2009 } |
|
2010 } |
|
2011 } |
|
2012 return KErrNotSupported; |
|
2013 } |
|
2014 |
|
2015 void CUpsTransportFlowShim::SubConnectionError(const Messages::TEBase::TError& aErrorMsg, TUint anOperationMask) |
|
2016 /** |
|
2017 Handle errors from SCpr |
|
2018 |
|
2019 @param aErrorMsg The incoming TError message |
|
2020 @param anOperationMask Pending operations to be error'd. |
|
2021 */ |
|
2022 { |
|
2023 if (aErrorMsg.iMsgId == UpsMessage::TPolicyCheckRequest::Id()) |
|
2024 { |
|
2025 // Previously sent TPolicyCheckRequest failed. |
|
2026 SetPolicyCheckRequestPending(EFalse); |
|
2027 ProcessDCIdleState(); |
|
2028 } |
|
2029 |
|
2030 CTransportFlowShim::SubConnectionError(aErrorMsg, anOperationMask); |
|
2031 } |
|
2032 |
|
2033 TBool CUpsTransportFlowShim::ActivityRunning() |
|
2034 /** |
|
2035 Determine whether we are in the middle of NoBearer or PolicyCheckRequest processing. |
|
2036 |
|
2037 In other words, we are waiting for a response from a previously transmitted TNoBearer |
|
2038 or TPolicyCheckRequest. |
|
2039 |
|
2040 @return ETrue if in the middle of one of this activity, else EFalse. |
|
2041 */ |
|
2042 { |
|
2043 return PolicyCheckRequestPending() || CTransportFlowShim::ActivityRunning(); |
|
2044 } |
|
2045 |
|
2046 #endif //f_NETWORKING_UPS |
|
2047 |
|
2048 |
|
2049 |
|
2050 //Register the class variable |
|
2051 START_ATTRIBUTE_TABLE(CSAPSetOpt,CSAPSetOpt::EUid, CSAPSetOpt::ETypeId) |
|
2052 END_ATTRIBUTE_TABLE() |
|
2053 |
|
2054 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
2055 //Set the protocol options |
|
2056 void CTransportFlowShim::SetProtocolOptions() |
|
2057 { |
|
2058 if(iProvider && iProtocolOptions) |
|
2059 { |
|
2060 for(TInt iter = 0; iter < iProtocolOptions->iOption.Count(); iter++) |
|
2061 { |
|
2062 TPtr8 optionDesProtOptVal( (TUint8*)&(iProtocolOptions->iOption[iter].iOptionValue), sizeof(TUint), sizeof(TUint) ); |
|
2063 iProvider->SetOption(iProtocolOptions->iOption[iter].iOptionName,iProtocolOptions->iOption[iter].iOptionLevel, optionDesProtOptVal); |
|
2064 } |
|
2065 } |
|
2066 } |
|
2067 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
2068 |
|
2069 EXPORT_C CSAPSetOpt::CSAPSetOpt() |
|
2070 { |
|
2071 } |
|
2072 |
|
2073 CSAPSetOpt::~CSAPSetOpt() |
|
2074 { |
|
2075 //Free the RArray resources. |
|
2076 iOption.Close(); |
|
2077 } |
|
2078 |
|
2079 //Add the option to the RArray variable |
|
2080 EXPORT_C void CSAPSetOpt::AddProtocolOptionL(TUint aOptionName, TUint aOptionLevel, TUint aOptionValue) |
|
2081 { |
|
2082 TProtocolOption opt; |
|
2083 opt.iOptionName = aOptionName; |
|
2084 opt.iOptionLevel = aOptionLevel; |
|
2085 opt.iOptionValue = aOptionValue; |
|
2086 iOption.AppendL(opt); |
|
2087 } |
|
2088 |
|
2089 //Update the value for an option |
|
2090 EXPORT_C void CSAPSetOpt::UpdateProtocolOption(TUint aOptionName, TUint aOptionLevel, TUint aOptionValue) |
|
2091 { |
|
2092 for(TInt i = 0; i < iOption.Count(); i++) |
|
2093 if((iOption[i].iOptionName == aOptionName) && (iOption[i].iOptionLevel == aOptionLevel)) |
|
2094 iOption[i].iOptionValue = aOptionValue; |
|
2095 } |
|
2096 |
|
2097 |
|
2098 |