|
1 // Copyright (c) 2004-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 #include "ss_subconnflow.h" |
|
16 |
|
17 |
|
18 #include <comms-infras/ss_log.h> |
|
19 #include <comms-infras/ss_mcprnodemessages.h> |
|
20 #include <comms-infras/ss_protflow.h> |
|
21 #include <es_ini.h> |
|
22 #include <ss_glob.h> |
|
23 #include <ss_protprov.h> |
|
24 #include <comms-infras/ss_sapshim.h> |
|
25 #include "ss_sapfactshim.h" |
|
26 #include <elements/cftransport.h> |
|
27 #include <ecom/ecom.h> |
|
28 #include <elements/nm_messages_child.h> |
|
29 |
|
30 #include <comms-infras/ss_nodemessages_factory.h> |
|
31 |
|
32 |
|
33 #ifdef _DEBUG |
|
34 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
35 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
36 _LIT(KSpecAssert_ESockSSocksbcnfl, "ESockSSocksbcnfl"); |
|
37 #endif |
|
38 |
|
39 using namespace ESock; |
|
40 using namespace Messages; |
|
41 using namespace CommsFW; |
|
42 using namespace Factories; |
|
43 |
|
44 |
|
45 //-===================================================================== |
|
46 // |
|
47 // |
|
48 // CSubConnectionFlowFactoryContainer |
|
49 // |
|
50 // |
|
51 //-===================================================================== |
|
52 CSubConnectionFlowFactoryContainer::CSubConnectionFlowFactoryContainer() |
|
53 :CCommsFactoryContainer((CCommsFactoryContainer::TContaineeType)CSubConnectionFlowFactoryContainer::EId) |
|
54 { |
|
55 LOG_NODE_CREATE(KESockDataFactTag, CSubConnectionFlowFactoryContainer) |
|
56 } |
|
57 |
|
58 CSubConnectionFlowFactoryContainer::~CSubConnectionFlowFactoryContainer() |
|
59 { |
|
60 TCFLegacyMessage::DeRegister(); |
|
61 LOG_NODE_DESTROY(KESockDataFactTag, CSubConnectionFlowFactoryContainer) |
|
62 } |
|
63 |
|
64 CSubConnectionFlowFactoryContainer* CSubConnectionFlowFactoryContainer::NewL() |
|
65 /** Create a new instance of a sub-connection factory container |
|
66 |
|
67 @exception Leaves in out of memory conditions |
|
68 @return Pointer to new instance of a sub-connection factory container |
|
69 */ |
|
70 { |
|
71 using namespace CommsFW; |
|
72 LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryContainer:\tNewL()")) ); |
|
73 |
|
74 // For the self-dispatching TLegacyConnectionEnumRequest |
|
75 TCFLegacyMessage::RegisterL(); |
|
76 |
|
77 CSubConnectionFlowFactoryContainer* provcont = new (ELeave) CSubConnectionFlowFactoryContainer(); |
|
78 CleanupStack::PushL(provcont); |
|
79 CTransportFlowShimFactory::NewL(TUid::Uid(CTransportFlowShimFactory::iUid), *provcont); |
|
80 CleanupStack::Pop(provcont); |
|
81 return provcont; |
|
82 } |
|
83 |
|
84 void CSubConnectionFlowFactoryContainer::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage) |
|
85 { |
|
86 if (aMessage.IsMessage<TCFFactory::TFindOrCreatePeer>()) |
|
87 { |
|
88 TCFFactory::TFindOrCreatePeer& msg = message_cast<TCFFactory::TFindOrCreatePeer>(aMessage); |
|
89 CCommsFactoryBase* factory = static_cast<CCommsFactoryBase*>(FindOrCreateFactoryL(msg.iUid)); |
|
90 ACommsFactoryNodeId* flow = factory->FindOrCreateObjectL(*(msg.iQuery)); |
|
91 |
|
92 // Send "DataClientJoined" |
|
93 #ifndef __GCCXML__ |
|
94 RClientInterface::OpenPostMessageClose(Id(), aSender, |
|
95 TCFFactory::TPeerFoundOrCreated(flow? flow->Id() : TNodeId::NullId(), 0).CRef()); |
|
96 #endif |
|
97 aMessage.ClearMessageId(); |
|
98 } |
|
99 else |
|
100 { |
|
101 NM_LOG_START_BLOCK(KESockMetaConnectionTag, _L8("CSubConnectionFlowFactoryContainer:ReceivedL")); |
|
102 NM_LOG((KESockMetaConnectionTag, _L8("ERROR: KErrNotSupported [this=0x%08x] "), this)); |
|
103 NM_LOG_MESSAGE(KESockMetaConnectionTag, aMessage); |
|
104 NM_LOG_END_BLOCK(KESockMetaConnectionTag, _L8("CSubConnectionFlowFactoryContainer:ReceivedL")); |
|
105 |
|
106 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksbcnfl, 1)); //For debug configurations |
|
107 User::Leave(KErrNotSupported); //For release configurations |
|
108 } |
|
109 } |
|
110 |
|
111 |
|
112 |
|
113 //-===================================================================== |
|
114 // |
|
115 // |
|
116 // CSubConnectionFlowFactoryBase |
|
117 // |
|
118 // |
|
119 //-===================================================================== |
|
120 EXPORT_C CSubConnectionFlowFactoryBase::CSubConnectionFlowFactoryBase(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer) |
|
121 /** Sub-connection flow factory constructor |
|
122 |
|
123 @param aFactoryId Unique Integer Identifier of the sub-connection provider factory |
|
124 @param aParentContainer Container to add the factory to */ |
|
125 : CCommsFactoryBase(aFactoryId, aParentContainer) |
|
126 { |
|
127 } |
|
128 |
|
129 EXPORT_C ACommsFactoryNodeId* CSubConnectionFlowFactoryBase::DoCreateObjectL(TFactoryQueryBase& aQuery) |
|
130 { |
|
131 const TDefaultFlowFactoryQuery& flowQuery = static_cast<const TDefaultFlowFactoryQuery&>(aQuery); |
|
132 TDefaultProtocolIntfFactoryQuery pintfQuery (flowQuery.iCprId); |
|
133 |
|
134 CProtocolIntfBase* proto = SockManGlobals::Get()->iProtocolIntfFactories->FindOrCreateProtocolIntfL(Uid(), pintfQuery); |
|
135 if (NULL == proto) |
|
136 { |
|
137 LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryBase %08x:\tCreateFlowL(protocolId '%08x') Cannot find protocol interface, bailing out"), this, Uid()) ); |
|
138 User::Leave(KErrNotFound); |
|
139 } |
|
140 // A null CPR indicates that there is no real control side at all, meaning it's a legacy protocol and the FlowRequest is puppeteering this |
|
141 // creation. In such a case we must be creating a CTransportFlowShim, which understands that a null SCPR is to be ignored |
|
142 __ASSERT_DEBUG(!flowQuery.iCprId.IsNull() || proto->Factory().Uid().iUid == CTransportFlowShimFactory::iUid, User::Panic(KSpecAssert_ESockSSocksbcnfl, 2)); |
|
143 ACommsFactoryNodeId* flow = DoCreateFlowL(proto, aQuery); |
|
144 LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryBase %08x:\tCreateFlowL(protocolId '%08x'): flow %08x"), this, Uid(), &flow) ); |
|
145 return flow; |
|
146 } |
|
147 |
|
148 EXPORT_C TServerProtocolDesc* CSubConnectionFlowFactoryBase::CreateFlowDescriptionL(TInt aProtocol) |
|
149 { |
|
150 // Defer to derived implementation |
|
151 return DoCreateFlowDescriptionL(aProtocol); |
|
152 } |
|
153 |
|
154 EXPORT_C TServerProtocolDesc* CSubConnectionFlowFactoryBase::DoCreateFlowDescriptionL(TInt /*aProtocol*/) |
|
155 { |
|
156 __ASSERT_DEBUG(0, Panic(EMisconfigured)); |
|
157 User::Leave(KErrNotSupported); |
|
158 return NULL; |
|
159 } |
|
160 |
|
161 EXPORT_C CSubConnectionFlowFactoryBase::~CSubConnectionFlowFactoryBase() |
|
162 { |
|
163 } |
|
164 |
|
165 |
|
166 |
|
167 //-===================================================================== |
|
168 // Default PINT |
|
169 //-===================================================================== |
|
170 class CDefaultProtocolIntf : public CProtocolIntfBase |
|
171 /** |
|
172 This is the internal, dummy, default CProtocolIntfBase implementation |
|
173 that will by default accompany any flow unless the flow factory |
|
174 decides to overload its CreateProtocolIntfFactoryL method. |
|
175 |
|
176 @internalTechnology |
|
177 */ |
|
178 { |
|
179 public: |
|
180 CDefaultProtocolIntf(CProtocolIntfFactoryBase& aFactory,const Messages::TNodeId& aCprId); |
|
181 |
|
182 // from CProtocolIntfBase |
|
183 virtual void DoFlowCreated(ESock::CSubConnectionFlowBase& aFlow); |
|
184 virtual void DoFlowBeingDeleted(ESock::CSubConnectionFlowBase& aFlow); |
|
185 }; |
|
186 |
|
187 class CDefaultProtocolIntfFactory : public CProtocolIntfFactoryBase |
|
188 /** |
|
189 This is the internal, dummy, default CProtocolIntfBase implementation |
|
190 that will by default accompany any flow unless the flow factory |
|
191 decides to overload its CreateProtocolIntfFactoryL method. |
|
192 |
|
193 @internalTechnology |
|
194 */ |
|
195 { |
|
196 public: |
|
197 virtual CProtocolIntfBase* DoCreateProtocolIntfL(TFactoryQueryBase& aQuery); |
|
198 static CDefaultProtocolIntfFactory* NewL(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer); |
|
199 protected: |
|
200 CDefaultProtocolIntfFactory(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer); |
|
201 }; |
|
202 CDefaultProtocolIntfFactory* CDefaultProtocolIntfFactory::NewL(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer) |
|
203 { |
|
204 CDefaultProtocolIntfFactory* factory = new (ELeave) CDefaultProtocolIntfFactory(aFactoryId, aParentContainer); |
|
205 CleanupStack::PushL(factory); |
|
206 factory->ConstructL(); |
|
207 CleanupStack::Pop(factory); |
|
208 return factory; |
|
209 } |
|
210 |
|
211 CDefaultProtocolIntf::CDefaultProtocolIntf(CProtocolIntfFactoryBase& aFactory,const Messages::TNodeId& aCprId) |
|
212 :CProtocolIntfBase(aFactory,aCprId) |
|
213 { |
|
214 } |
|
215 |
|
216 void CDefaultProtocolIntf::DoFlowCreated(ESock::CSubConnectionFlowBase& /*aFlow*/) |
|
217 { |
|
218 } |
|
219 |
|
220 void CDefaultProtocolIntf::DoFlowBeingDeleted(ESock::CSubConnectionFlowBase& /*aFlow*/) |
|
221 { |
|
222 } |
|
223 |
|
224 CProtocolIntfBase* CDefaultProtocolIntfFactory::DoCreateProtocolIntfL(TFactoryQueryBase& aQuery) |
|
225 { |
|
226 const TDefaultProtocolIntfFactoryQuery& query = static_cast<const TDefaultProtocolIntfFactoryQuery&>(aQuery); |
|
227 return new (ELeave) CDefaultProtocolIntf(*this,query.iCprId); |
|
228 } |
|
229 |
|
230 CDefaultProtocolIntfFactory::CDefaultProtocolIntfFactory(TUid aFactoryId, CProtocolIntfFactoryContainer& aParentContainer) |
|
231 : CProtocolIntfFactoryBase(aFactoryId, aParentContainer) |
|
232 { |
|
233 } |
|
234 |
|
235 EXPORT_C CProtocolIntfFactoryBase* CSubConnectionFlowFactoryBase::CreateProtocolIntfFactoryL(CProtocolIntfFactoryContainer& aParentContainer) |
|
236 { |
|
237 return CDefaultProtocolIntfFactory::NewL (Uid(), aParentContainer); |
|
238 } |
|
239 |
|
240 |
|
241 //-===================================================================== |
|
242 // |
|
243 // |
|
244 // CSubConnectionFlowBase |
|
245 // |
|
246 // |
|
247 //-===================================================================== |
|
248 EXPORT_C CSubConnectionFlowBase::CSubConnectionFlowBase(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, |
|
249 CProtocolIntfBase* aProtocolIntf) |
|
250 : ACommsFactoryNodeId(aFactory), |
|
251 iProtocolIntf(aProtocolIntf) |
|
252 { |
|
253 __ASSERT_DEBUG(iProtocolIntf, User::Panic(KSpecAssert_ESockSSocksbcnfl, 3)); |
|
254 iSubConnectionProvider.Open(aSubConnId); |
|
255 // Signal the ProtocolIntf that a Flow has been created. |
|
256 iProtocolIntf->FlowCreated(*this); |
|
257 } |
|
258 |
|
259 EXPORT_C CSubConnectionFlowBase::~CSubConnectionFlowBase() |
|
260 { |
|
261 if(iLastRequestOriginator.IsOpen()) |
|
262 { |
|
263 iLastRequestOriginator.ReplyTo(Id(), TEChild::TLeft().CRef()); |
|
264 } |
|
265 iProtocolIntf->FlowBeingDeleted(*this); |
|
266 LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowBase %08x:\t~CSubConnectionFlowBase"), this) ); |
|
267 } |
|
268 |
|
269 EXPORT_C void CSubConnectionFlowBase::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage) |
|
270 { |
|
271 if (iLastRequestOriginator.Open(iSubConnectionProvider, aSender) != KErrNone) |
|
272 { |
|
273 if(!iSubConnectionProvider.IsOpen()) |
|
274 { |
|
275 // Legacy flows legitimately lack a sub-connection provider |
|
276 return; |
|
277 } |
|
278 else if(aMessage.IsMessage<TEBase::TError>()) |
|
279 { |
|
280 //[TODO EC120] RZ: WHoa! What is this?! Flow receives a TError and as a response sends TError |
|
281 //(leaves from ::ReceivedL are handled by sending TError). |
|
282 __ASSERT_DEBUG(static_cast<TEBase::TError&>(aMessage).iValue != KErrNone, User::Panic(KSpecAssert_ESockSSocksbcnfl, 4)); |
|
283 User::Leave(static_cast<TEBase::TError&>(aMessage).iValue); // don't mutate the error into KErrArgument |
|
284 } |
|
285 User::Leave(KErrArgument); |
|
286 } |
|
287 } |
|
288 |
|
289 EXPORT_C void CSubConnectionFlowBase::SubConnectionGoingDown() |
|
290 { |
|
291 LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowBase %08x:\tSubConnectionGoingDown"), this) ); |
|
292 iSubConnectionProvider.Close(); |
|
293 DeleteThisFlow(); |
|
294 } |
|
295 |
|
296 EXPORT_C NetInterfaces::TInterfaceControl* CSubConnectionFlowBase::FetchNodeInterfaceControlL(TInt aInterfaceId) |
|
297 { |
|
298 return DoFetchInterfaceControlL(aInterfaceId); |
|
299 } |
|
300 |
|
301 EXPORT_C MFlowBinderControl* CSubConnectionFlowBase::GetBinderControlL() |
|
302 { |
|
303 return DoGetBinderControlL(); |
|
304 } |
|
305 |
|
306 EXPORT_C void CSubConnectionFlowBase::DeleteThisFlow() |
|
307 /** |
|
308 Called from Flows to delete themselves, usually as a result of a received Destroy() message. |
|
309 |
|
310 */ |
|
311 { |
|
312 |
|
313 DeleteMeNow(); |
|
314 // "this" no longer valid after this point. |
|
315 |
|
316 } |
|
317 |
|
318 EXPORT_C CProtocolIntfBase* CSubConnectionFlowBase::ProtocolIntf() const |
|
319 /** |
|
320 Return the ProtocolIntf associated with this Flow |
|
321 */ |
|
322 { |
|
323 return iProtocolIntf; |
|
324 } |
|
325 |
|
326 |