|
1 // Copyright (c) 2008-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 // @internalComponent |
|
15 // |
|
16 // |
|
17 |
|
18 //System Includes |
|
19 #include <comms-infras/ss_nodeinterfaces.h> |
|
20 #include <comms-infras/ss_nodemessages_factory.h> |
|
21 #include <ss_glob.h> |
|
22 |
|
23 //Local Includes |
|
24 #include "httpmudpflow.h" |
|
25 #include "upnppint.h" |
|
26 #include "upnpctrlscprstates.h" |
|
27 #include "upnpstatemachine.h" |
|
28 #include "upnpserverconstants.h" |
|
29 #include "upnplog.h" |
|
30 #include "upnpmemoryutils.h" |
|
31 |
|
32 #include <http/thttptable.h> |
|
33 #include <http/framework/cheadercodecplugin.h> |
|
34 #include <httpstringconstants.h> |
|
35 #include <upnp/tupnptable.h> |
|
36 #include <e32math.h> |
|
37 |
|
38 const TUint KDeftMaxAgeVal = 1800; |
|
39 |
|
40 __FLOG_STMT(_LIT8(KComponent,"Flow");) |
|
41 CHttpMUdpFlow* CHttpMUdpFlow::NewL ( CSubConnectionFlowFactoryBase& aFactory, |
|
42 CUPnPProtocolIntfBase* aProtocolIntf, |
|
43 const TNodeId& aSubConnId ) |
|
44 { |
|
45 CHttpMUdpFlow* self = new ( ELeave )CHttpMUdpFlow ( aFactory, aProtocolIntf, aSubConnId ); |
|
46 CleanupStack::PushL ( self ); |
|
47 self->ConstructL (); |
|
48 CleanupStack::Pop (); // self |
|
49 return self; |
|
50 } |
|
51 |
|
52 CHttpMUdpFlow::CHttpMUdpFlow ( CSubConnectionFlowFactoryBase& aFactory, |
|
53 CUPnPProtocolIntfBase* aProtocolIntf, |
|
54 const TNodeId& aSubConnId ) |
|
55 : CUPnPFlowBase ( aFactory, aProtocolIntf, EHttpMUdpFlow, aSubConnId ), iIsStarted ( EFalse ), iIsLeaving ( EFalse ) |
|
56 { |
|
57 LOG_NODE_CREATE(KESockFlowTag, CHttpMUdpFlow); |
|
58 } |
|
59 |
|
60 CHttpMUdpFlow::~CHttpMUdpFlow () |
|
61 { |
|
62 delete iRequestParser; |
|
63 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iReceivedData"))); |
|
64 if ( !iReceivedData.IsEmpty () ) |
|
65 iReceivedData.Free (); |
|
66 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iUPnPRequest"))); |
|
67 delete iUPnPRequest; |
|
68 iRecvElements.Reset (); |
|
69 //delete iCodec; |
|
70 |
|
71 __ASSERT_DEBUG ( iSearchTargetArray.Count () == 0, User::Invariant () ); |
|
72 iSearchTargetArray.Close (); |
|
73 __ASSERT_DEBUG ( iNotifyTargetArray.Count () == 0, User::Invariant () ); |
|
74 iNotifyTargetArray.Close (); |
|
75 iListenRequestors.Reset (); |
|
76 |
|
77 iStringPool.Close(); |
|
78 |
|
79 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iSubConnectionProvider"))); |
|
80 iSubConnectionProvider.Close (); |
|
81 __ASSERT_DEBUG ( iTimerMappedArray.Count () == 0, User::Invariant () ); |
|
82 iTimerMappedArray.ResetAndDestroy(); |
|
83 __ASSERT_DEBUG ( iCallbackArray.Count () == 0, User::Invariant () ); |
|
84 iCallbackArray.ResetAndDestroy(); |
|
85 if ( iDeltaTimer ) |
|
86 iDeltaTimer->Cancel(); |
|
87 delete iDeltaTimer; |
|
88 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroyed CHttpMUdpFlow"))); |
|
89 LOG_NODE_DESTROY(KESockFlowTag, CHttpMUdpFlow); |
|
90 } |
|
91 |
|
92 |
|
93 void CHttpMUdpFlow::ConstructL () |
|
94 { |
|
95 TAppProtIntfMessage::RegisterL (); // Register the message with COMMS transport |
|
96 iStringPool.OpenL(TUPnPTable::Table()); |
|
97 iStringPool.OpenL(THTTPTable::Table()); |
|
98 iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool ); |
|
99 iRequestParser = CUpnpRequestParser::NewL ( *this ); |
|
100 iUPnPRequest = CRequest::NewL ( *iCodec, iStringPool ); |
|
101 // Create a delta timer with the given priority |
|
102 iDeltaTimer=CDeltaTimer::NewL(EPriorityLow); |
|
103 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Created CHttpMUdpFlow"))); |
|
104 } |
|
105 |
|
106 void CHttpMUdpFlow::ReceivedL ( const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage ) |
|
107 { |
|
108 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL"))); |
|
109 |
|
110 if ( aMessage.IsMessage<TEChild::TDestroy> () ) |
|
111 { |
|
112 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDestroy"))); |
|
113 if ( RemoveControlClient ( FindControlClient ( address_cast<TNodeId> ( aSender ) ) ) == 0 ) |
|
114 { |
|
115 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDestroy - Deleting current flow"))); |
|
116 DeleteThisFlow (); |
|
117 } |
|
118 } |
|
119 else if ( aMessage.IsMessage<TCFDataClient::TStart> () ) |
|
120 { |
|
121 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDataClientStart"))); |
|
122 StartFlow ( address_cast<TNodeCtxId> ( aSender ) ); |
|
123 } |
|
124 else if ( aMessage.IsMessage<TCFDataClient::TStop> () ) |
|
125 { |
|
126 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPStopSearch"))); |
|
127 |
|
128 Unregister ( address_cast<TNodeCtxId> ( aSender ) ); |
|
129 StopFlow ( address_cast<TNodeCtxId> ( aSender ) ); |
|
130 } |
|
131 else if ( aMessage.IsMessage<TCFFactory::TPeerFoundOrCreated> () ) |
|
132 { |
|
133 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TFOCreated"))); |
|
134 const TCFFactory::TPeerFoundOrCreated& msg = message_cast < const TCFFactory::TPeerFoundOrCreated > ( aMessage ); |
|
135 iAppProtIntfId = msg.iNodeId; |
|
136 |
|
137 TAppProtAddr mCastAddr( KSsdpMulticastAddr, KUpnpMCPort ); |
|
138 RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TJoinWithMulticastAddress ( mCastAddr ).CRef () ); |
|
139 } |
|
140 else if ( TAppProtIntfMessage::ERealmId == aMessage.MessageId ().Realm () ) |
|
141 { |
|
142 switch ( aMessage.MessageId ().MessageId () ) |
|
143 { |
|
144 case TAppProtIntfMessage::TJoinComplete::EId: |
|
145 { |
|
146 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TJoinComplete"))); |
|
147 iIsStarted = ETrue; |
|
148 for ( TInt i = 0; i < iListenRequestors.Count (); i++ ) |
|
149 { |
|
150 RClientInterface::OpenPostMessageClose ( NodeId (), iListenRequestors[i], TCFDataClient::TStarted ().CRef () ); |
|
151 } |
|
152 |
|
153 iListenRequestors.Reset (); |
|
154 } |
|
155 break; |
|
156 |
|
157 case TAppProtIntfMessage::TLeaveComplete::EId: |
|
158 { |
|
159 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TLeaveComplete"))); |
|
160 // post destroy to service provider |
|
161 RClientInterface::OpenPostMessageClose ( NodeId (), iAppProtIntfId, TAppProtIntfMessage::TDestroy ().CRef () ); |
|
162 // post dataclient stopped to controlprovider |
|
163 PostDataClientStopped ( iLastLeavingClient ); |
|
164 } |
|
165 break; |
|
166 |
|
167 case TAppProtIntfMessage::TDataReceived::EId: |
|
168 { |
|
169 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TDataReceived"))); |
|
170 TAppProtIntfMessage::TDataReceived& msg = message_cast <TAppProtIntfMessage::TDataReceived> ( aMessage ); |
|
171 |
|
172 if ( !iIsLeaving ) |
|
173 { |
|
174 RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager()); |
|
175 RMemChunk memChunk; |
|
176 TUPnPMemoryUtils::CreateMemChunk(memChunk, msg.iData, allocator); |
|
177 |
|
178 CRecvElement* element = new ( ELeave ) CRecvElement ( memChunk, msg.iAddr ); |
|
179 CleanupStack::PushL ( element ); |
|
180 iRecvElements.AppendL ( element ); |
|
181 CleanupStack::Pop ( element ); |
|
182 ParseIfOneRecvElement (); |
|
183 } |
|
184 msg.iData.Free (); |
|
185 } |
|
186 break; |
|
187 |
|
188 case TAppProtIntfMessage::TError::EId: |
|
189 { |
|
190 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TError"))); |
|
191 // Note! Nothing to do if already leaving state, |
|
192 // else need to send error to control clients and do listener cleanup |
|
193 } |
|
194 break; |
|
195 |
|
196 default: |
|
197 break; |
|
198 } |
|
199 } |
|
200 else if ( TUpnpMessage::ERealmId == aMessage.MessageId ().Realm () ) |
|
201 { |
|
202 switch ( aMessage.MessageId ().MessageId () ) |
|
203 { |
|
204 case TUpnpMessage::TUPnPNotifyRegistration::EId: |
|
205 { |
|
206 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPNotifyRegistration"))); |
|
207 RegisterL ( address_cast<TNodeCtxId> ( aSender ), |
|
208 static_cast < TUpnpMessage::TUPnPNotifyRegistration& > ( aMessage ).iSsdpInfo.iSearchTarget, |
|
209 iNotifyTargetArray ); |
|
210 } |
|
211 break; |
|
212 |
|
213 case TUpnpMessage::TUPnPPublishRegistration::EId: |
|
214 { |
|
215 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPPublishRegistration"))); |
|
216 RegisterL ( address_cast<TNodeCtxId> ( aSender ), |
|
217 static_cast < TUpnpMessage::TUPnPPublishRegistration& > ( aMessage ).iSsdpInfo.iSearchTarget, |
|
218 iSearchTargetArray ); |
|
219 } |
|
220 break; |
|
221 |
|
222 case TUpnpMessage::TCancelRequest::EId: |
|
223 { |
|
224 Unregister ( address_cast<TNodeCtxId> ( aSender ) ); |
|
225 RClientInterface::OpenPostMessageClose ( NodeId (), address_cast<TNodeCtxId> ( aSender ), TUpnpMessage::TCancelled ().CRef () ); |
|
226 } |
|
227 break; |
|
228 } |
|
229 } |
|
230 } |
|
231 |
|
232 |
|
233 void CHttpMUdpFlow::StartFlow ( TNodeCtxId aSender ) |
|
234 { |
|
235 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("HttpMUdpFlow::StartFlow"))); |
|
236 if ( iIsStarted ) |
|
237 { |
|
238 RClientInterface::OpenPostMessageClose ( NodeId (), aSender, TCFDataClient::TStarted ().CRef () ); |
|
239 return; |
|
240 } |
|
241 |
|
242 if ( !iIsStarted && iListenRequestors.Count () == 0 ) |
|
243 { |
|
244 iListenRequestors.Append ( aSender ); |
|
245 CreateMulticastListener (); |
|
246 iIsLeaving = EFalse; |
|
247 } |
|
248 |
|
249 } |
|
250 |
|
251 void CHttpMUdpFlow::StopFlow ( TNodeCtxId aSender ) |
|
252 { |
|
253 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::StopFlow"))); |
|
254 |
|
255 SetClientLeaving ( aSender ); // set the control client leaving |
|
256 |
|
257 if ( iIsStarted && CheckIfAllClientsLeaving ( ) ) |
|
258 { |
|
259 MarkMeForDeletion (); |
|
260 iLastLeavingClient = aSender; |
|
261 iIsLeaving = ETrue; |
|
262 iIsStarted = EFalse; |
|
263 |
|
264 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::StopFlow - Posting message TAppProtIntfMessage::TLeave"))); |
|
265 // leaving service provider |
|
266 RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TClientLeavingRequest ().CRef () ); |
|
267 } |
|
268 else |
|
269 { |
|
270 PostDataClientStopped ( aSender ); |
|
271 } |
|
272 } |
|
273 |
|
274 void CHttpMUdpFlow::ParseIfOneRecvElement () |
|
275 { |
|
276 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseIfOneRecvElement"))); |
|
277 if ( iRecvElements.Count () == 1 ) |
|
278 { |
|
279 ParseElement (); |
|
280 } |
|
281 } |
|
282 |
|
283 void CHttpMUdpFlow::ParseElement () |
|
284 { |
|
285 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseElement"))); |
|
286 if ( iRecvElements.Count () > 0 ) |
|
287 { |
|
288 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseElement - Parsing request"))); |
|
289 iRequestParser->ParseRequest ( iRecvElements[0]->Data (), iUPnPRequest ); |
|
290 } |
|
291 } |
|
292 |
|
293 void CHttpMUdpFlow::RemoveFirstRecvElement () |
|
294 { |
|
295 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::RemoveFirstRecvElement"))); |
|
296 ASSERT ( iRecvElements.Count () > 0 ); |
|
297 CRecvElement* element = iRecvElements[0]; |
|
298 iRecvElements.Remove (0); |
|
299 delete element; |
|
300 } |
|
301 |
|
302 // From MParserObserver |
|
303 void CHttpMUdpFlow::GotHeaders () |
|
304 { |
|
305 if ( ValidateRequest () != KErrNone ) |
|
306 { |
|
307 DataParsed (); |
|
308 } |
|
309 |
|
310 // Else we will notify to the SCPR(s) from ParsingComplete. |
|
311 } |
|
312 |
|
313 void CHttpMUdpFlow::DataParsed() |
|
314 { |
|
315 // Bad data. This is UDP. we should get everything or none |
|
316 iRequestParser->DataFailed (); |
|
317 iRequestParser->ResetParser (); |
|
318 RemoveFirstRecvElement (); |
|
319 ParseElement (); |
|
320 } |
|
321 |
|
322 void CHttpMUdpFlow::ParsingComplete ( RMemChunk& /*aExcessData*/ ) |
|
323 { |
|
324 NotifyClients (); |
|
325 DataParsed (); |
|
326 iUPnPRequest->Reset(); |
|
327 } |
|
328 |
|
329 void CHttpMUdpFlow::ParserError ( TInt /*aError*/ ) |
|
330 { |
|
331 DataParsed (); // Bad data. |
|
332 } |
|
333 |
|
334 |
|
335 void CHttpMUdpFlow::NotifyClients () |
|
336 { |
|
337 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients"))); |
|
338 TInt method = iUPnPRequest->Handle ().Method ().Index ( TUPnPTable::Table() ); |
|
339 if ( method == UPnP::ENotify ) //control point end listening for notify packets |
|
340 { |
|
341 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients - Handling NOTIFY request"))); |
|
342 TRAP_IGNORE ( HandleNotifyRequestL () ); |
|
343 } |
|
344 else //if ( method == UPnP::EMSearch ) //service point end listening for m-search packets |
|
345 { |
|
346 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients - Handling MSEARCH request"))); |
|
347 // CreateTimerEntry sets iEntry to the new timer entry and queues it in the deltatimer |
|
348 TRAP_IGNORE ( CreateTimerEntryL() ); |
|
349 } |
|
350 |
|
351 return; |
|
352 } |
|
353 |
|
354 void CHttpMUdpFlow::ReadRequestValues ( RStringF& aLocation, TInt& aMaxAge ) |
|
355 { |
|
356 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - ST, USN, Location values"))); |
|
357 THTTPHdrVal value; |
|
358 GetHeaderValue ( *iUPnPRequest, HTTP::ELocation, value , THTTPTable::Table()); |
|
359 aLocation = value.StrF (); |
|
360 |
|
361 value.SetInt(KDeftMaxAgeVal); |
|
362 GetParamValue ( *iUPnPRequest, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table() ); |
|
363 aMaxAge = value.Int(); |
|
364 } |
|
365 |
|
366 void CHttpMUdpFlow::ReadRequestValues ( RStringF& aSt, RStringF& aUsn, RStringF& aNts) |
|
367 { |
|
368 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - ST, USN values"))); |
|
369 THTTPHdrVal value = RStringF(); |
|
370 GetHeaderValue ( *iUPnPRequest, UPnP::EUSN, value, TUPnPTable::Table() ); |
|
371 aUsn = value.StrF (); |
|
372 |
|
373 GetHeaderValue ( *iUPnPRequest, UPnP::ENT, value, TUPnPTable::Table() ); |
|
374 aSt = value.StrF (); |
|
375 |
|
376 GetHeaderValue ( *iUPnPRequest, UPnP::ENTS, value, TUPnPTable::Table() ); |
|
377 aNts = value.StrF (); |
|
378 } |
|
379 |
|
380 void CHttpMUdpFlow::ReadRequestValues ( TInt& aMaxAge, RStringF& aSt ) |
|
381 { |
|
382 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - Max-Age, NT values"))); |
|
383 THTTPHdrVal value; |
|
384 GetHeaderValue ( *iUPnPRequest, UPnP::EMX, value, TUPnPTable::Table() ); |
|
385 aMaxAge = value.Int(); |
|
386 |
|
387 GetHeaderValue ( *iUPnPRequest, UPnP::EST, value, TUPnPTable::Table() ); |
|
388 aSt = value.StrF (); |
|
389 } |
|
390 |
|
391 |
|
392 void CHttpMUdpFlow::HandleNotifyRequestL () |
|
393 { |
|
394 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest"))); |
|
395 RStringF usn; |
|
396 RStringF st; |
|
397 RStringF nts; |
|
398 RStringF location; |
|
399 TInt maxAge = 0; |
|
400 THTTPHdrVal value; |
|
401 ReadRequestValues ( st, usn, nts ); |
|
402 for ( TInt i = 0; i < iNotifyTargetArray.Count (); ++i ) |
|
403 { |
|
404 const CSearchTarget& target = *(iNotifyTargetArray[i]); |
|
405 |
|
406 if ( target.Match ( st.DesC() ) != KErrNotFound && |
|
407 !IsClientLeaving ( target.Originator () ) ) |
|
408 { |
|
409 // We have a match. Post the information to our control client |
|
410 RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager()); |
|
411 |
|
412 RMemChunk usnBuf; |
|
413 RMemChunk stBuf; |
|
414 usnBuf.CreateL ( usn.DesC (), allocator ); |
|
415 TCleanupItem item ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &usnBuf ); |
|
416 CleanupStack::PushL ( item ); |
|
417 stBuf.CreateL ( st.DesC (), allocator ); |
|
418 TCleanupItem item2 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &stBuf ); |
|
419 CleanupStack::PushL ( item2 ); |
|
420 if ( nts.DesC().CompareF ( KSsdpAlive ) == 0 ) |
|
421 { |
|
422 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest - Posting message TUpnpMessage::TUPnPPublishAliveRequest"))); |
|
423 ReadRequestValues ( location, maxAge ); |
|
424 RMemChunk locationBuf; |
|
425 locationBuf.CreateL ( location.DesC (), allocator ); |
|
426 TCleanupItem item3 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &locationBuf ); |
|
427 CleanupStack::PushL ( item3 ); |
|
428 |
|
429 TSsdpInfo info ( maxAge, locationBuf, usnBuf, stBuf ); |
|
430 RClientInterface::OpenPostMessageClose ( NodeId (), target.Originator (), TUpnpMessage::TUPnPPublishAliveRequest ( info ).CRef () ); |
|
431 |
|
432 CleanupStack::Pop (); // item3 |
|
433 } |
|
434 else |
|
435 { |
|
436 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest - Posting message TUpnpMessage::TUPnPPublishByeRequest"))); |
|
437 TSsdpInfo info ( usnBuf, stBuf ); |
|
438 RClientInterface::OpenPostMessageClose ( NodeId (), target.Originator (), TUpnpMessage::TUPnPPublishByeRequest ( info ).CRef () ); |
|
439 } |
|
440 CleanupStack::Pop (); // item2 |
|
441 CleanupStack::Pop (); // item3 |
|
442 } |
|
443 |
|
444 } |
|
445 } |
|
446 |
|
447 TInt CHttpMUdpFlow::HandleMSearchRequestL ( TAny* aPtr ) |
|
448 { |
|
449 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleMSearchRequest"))); |
|
450 CCallbackArgument* pointerData= static_cast<CCallbackArgument*> (aPtr); |
|
451 CHttpMUdpFlow* thisObject= static_cast < CHttpMUdpFlow* > (pointerData->GetThisPointer()); |
|
452 RPointerArray<CTimerMappedUri>& rArray=thisObject->GetTimerArray(); |
|
453 RPointerArray<CCallbackArgument>& argArray = thisObject->GetArgumentArray(); |
|
454 CTimerMappedUri* timerUri = NULL; |
|
455 for(TInt index=0; index < rArray.Count();index++) |
|
456 { |
|
457 if(rArray[index]->MatchTimerEntry( pointerData->GetTimerEntry() )) |
|
458 { |
|
459 // Removes the uri entry from the array |
|
460 timerUri = rArray[index]; |
|
461 rArray.Remove(index); |
|
462 break; |
|
463 } |
|
464 } |
|
465 TInt index = argArray.Find( pointerData ); |
|
466 __ASSERT_DEBUG(index >= 0 , User::Invariant()); |
|
467 argArray.Remove( index ); |
|
468 const CSearchTarget& target = *(pointerData->SearchTarget()); |
|
469 // We have a match. Post the information to our control client |
|
470 if ( !(thisObject->IsClientLeaving ( target.Originator () ) )) |
|
471 { |
|
472 RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( thisObject->ProtocolIntf () )->GetMemoryChunkManager()); |
|
473 RMemChunk stBuf; |
|
474 if ( timerUri->GetUri().CompareF(KSsdpAll) == 0 ) |
|
475 { |
|
476 stBuf.CreateL ( target.SearchTarget(), allocator ); |
|
477 } |
|
478 else |
|
479 { |
|
480 stBuf.CreateL ( timerUri->GetUri(), allocator ); |
|
481 } |
|
482 |
|
483 TSsdpInfo info ( stBuf, pointerData->GetAddress() ); |
|
484 RClientInterface::OpenPostMessageClose ( thisObject->NodeId (), target.Originator (), TUpnpMessage::TUPnPSearchRequest ( info ).CRef () ); |
|
485 } |
|
486 |
|
487 delete timerUri; |
|
488 delete pointerData; |
|
489 return KErrNone; |
|
490 } |
|
491 |
|
492 void CHttpMUdpFlow::RegisterL ( TNodeCtxId aChannelId, RMemChunk& aST, CSearchTargetArray& aArray ) |
|
493 { |
|
494 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::RegisterL"))); |
|
495 CSearchTarget* searchTarget = new ( ELeave ) CSearchTarget ( aChannelId ); |
|
496 CleanupStack::PushL ( searchTarget ); |
|
497 searchTarget->AddTargetL ( aST ); |
|
498 aArray.AppendL ( searchTarget ); |
|
499 CleanupStack::Pop (); // searchTarget |
|
500 } |
|
501 |
|
502 void CHttpMUdpFlow::Unregister ( TNodeCtxId aSender ) |
|
503 { |
|
504 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister"))); |
|
505 |
|
506 TBool isPublisher = EFalse; |
|
507 TInt i = iSearchTargetArray.Count () - 1; |
|
508 while ( i >= 0) |
|
509 { |
|
510 if ( aSender.Ptr () == iSearchTargetArray[i]->Originator ().Ptr () ) |
|
511 // for Published SCPR there is no activity running, |
|
512 // For Embedded and Root Device SCPR, there will be |
|
513 // multiple Entries in SearchTargetArray, which will be removed with |
|
514 // one TDataClientStop Message |
|
515 { |
|
516 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister - target found in search array"))); |
|
517 CSearchTarget *target = iSearchTargetArray[i]; |
|
518 iSearchTargetArray.Remove(i); |
|
519 CCallbackArgument* callArgument; |
|
520 TInt index = iCallbackArray.Count() - 1; |
|
521 while ( index >= 0 ) |
|
522 { |
|
523 if (target == iCallbackArray[index]->SearchTarget()) |
|
524 { |
|
525 callArgument = iCallbackArray[index]; |
|
526 iCallbackArray.Remove( index ); |
|
527 for ( TInt j = 0; j < iTimerMappedArray.Count (); j++ ) |
|
528 { |
|
529 if ( iTimerMappedArray[j]->MatchTimerEntry( callArgument->GetTimerEntry() ) ) |
|
530 { |
|
531 // Removes the uri entry from the array |
|
532 CTimerMappedUri* timerUri = iTimerMappedArray[j]; |
|
533 iDeltaTimer->Remove(timerUri->GetTimerEntry()); |
|
534 iTimerMappedArray.Remove(j); |
|
535 delete timerUri; |
|
536 break; |
|
537 } |
|
538 } |
|
539 delete callArgument; |
|
540 } |
|
541 --index; |
|
542 } |
|
543 |
|
544 delete target; |
|
545 isPublisher = ETrue; |
|
546 } |
|
547 |
|
548 --i; |
|
549 } |
|
550 if ( isPublisher ) |
|
551 { |
|
552 return; |
|
553 } |
|
554 |
|
555 for ( TInt i = 0; i < iNotifyTargetArray.Count (); ++i ) |
|
556 { |
|
557 if ( aSender == iNotifyTargetArray[i]->Originator () ) // for Register Notify if the activity is not running, |
|
558 // there will not be any Entry in NotifyTargetArray |
|
559 { |
|
560 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister - target found in notify array"))); |
|
561 CSearchTarget *target = iNotifyTargetArray[i]; |
|
562 iNotifyTargetArray.Remove(i); |
|
563 delete target; |
|
564 return; |
|
565 } |
|
566 } |
|
567 } |
|
568 |
|
569 void CHttpMUdpFlow::CreateMulticastListener () |
|
570 { |
|
571 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::CreateMulticastListener"))); |
|
572 const TInt KAppProtIntfFactoryUid = 0x2000D05B; // Put in common place |
|
573 //const TInt KGenericContainerIndex = 1; |
|
574 TAppProtIntfQuery query ( KProtocolInetUdp, KUpnpMCPort ); |
|
575 |
|
576 TCFFactory::TFindOrCreatePeer foMsg ( TCFPlayerRole::EDataPlane, TUid::Uid( KAppProtIntfFactoryUid ), &query ); |
|
577 // foMsg.PostTo ( SockManGlobals::Get()->GetPlaneFC ( EDataPlane, KGenericContainerIndex ) ); |
|
578 TNodeId containerId = static_cast<CUPnPProtocolIntfBase*>(ProtocolIntf())->GetAppProtIntfContainerId(); |
|
579 if ( containerId != TNodeId::NullId ( ) ) |
|
580 { |
|
581 RClientInterface::OpenPostMessageClose ( NodeId (), containerId, foMsg ); |
|
582 } |
|
583 } |
|
584 |
|
585 TInt CHttpMUdpFlow::ValidateRequest () |
|
586 { |
|
587 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest"))); |
|
588 TInt err = KErrNone; |
|
589 TInt method = iUPnPRequest->Handle ().Method ().Index ( TUPnPTable::Table() ); |
|
590 |
|
591 switch ( method ) |
|
592 { |
|
593 case UPnP::ENotify: |
|
594 { |
|
595 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating NOTIFY request"))); |
|
596 err = ValidateNotifyRequest (); |
|
597 } |
|
598 break; |
|
599 |
|
600 case UPnP::EMSearch: |
|
601 { |
|
602 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating MSEARCH request"))); |
|
603 err = ValidateMSearchRequest (); |
|
604 } |
|
605 break; |
|
606 |
|
607 default: |
|
608 err = KErrCorrupt; |
|
609 break; |
|
610 } |
|
611 |
|
612 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating returned with error code = %d"), err)); |
|
613 return err; |
|
614 } |
|
615 |
|
616 TInt CHttpMUdpFlow::ValidateNotifyRequest () |
|
617 { |
|
618 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateNotifyRequest"))); |
|
619 |
|
620 if ( IsHeaderPresent ( *iUPnPRequest, UPnP::ENTS, TUPnPTable::Table() ) != KErrNone ) |
|
621 return KErrCorrupt; |
|
622 |
|
623 THTTPHdrVal value; |
|
624 GetHeaderValue ( *iUPnPRequest, UPnP::ENTS, value, TUPnPTable::Table() ); |
|
625 if(value.StrF ().DesC().CompareF ( KSsdpBye )!= 0) |
|
626 { |
|
627 if ( IsValidCacheControlHeader ( *iUPnPRequest ) != KErrNone ) |
|
628 return KErrCorrupt; |
|
629 |
|
630 if ( IsHeaderPresent ( *iUPnPRequest, HTTP::ELocation, THTTPTable::Table() ) != KErrNone ) |
|
631 return KErrCorrupt; |
|
632 } |
|
633 |
|
634 if ( IsHeaderPresent ( *iUPnPRequest, UPnP::ENT, TUPnPTable::Table() ) != KErrNone ) |
|
635 return KErrCorrupt; |
|
636 |
|
637 return KErrNone; |
|
638 } |
|
639 |
|
640 TInt CHttpMUdpFlow::ValidateMSearchRequest () |
|
641 { |
|
642 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateMSearchRequest"))); |
|
643 if ( IsValidHostHeader ( *iUPnPRequest ) && IsValidManHeader ( *iUPnPRequest ) && |
|
644 IsHeaderPresent ( *iUPnPRequest, UPnP::EMX, TUPnPTable::Table() ) == KErrNone && IsHeaderPresent ( *iUPnPRequest, UPnP::EST, TUPnPTable::Table() ) == KErrNone ) |
|
645 return KErrNone; |
|
646 return KErrCorrupt; |
|
647 } |
|
648 |
|
649 TInt CHttpMUdpFlow::GetHeaderValue ( const CRequest& aRequest, TInt aFieldIndex, THTTPHdrVal& aFieldVal, const TStringTable& aTable ) const |
|
650 { |
|
651 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::GetHeaderValue"))); |
|
652 CRequest& request = const_cast < CRequest& > ( aRequest ); |
|
653 RRequest req = request.Handle (); |
|
654 RHTTPHeaders headers = req.GetHeaderCollection (); |
|
655 RStringF fieldStr = aRequest.StringPool ().StringF ( aFieldIndex, aTable ); |
|
656 return headers.GetField ( fieldStr, 0, aFieldVal ); |
|
657 } |
|
658 |
|
659 TInt CHttpMUdpFlow::GetParamValue ( const CRequest& aRequest , TInt aFieldIndex, TInt aParamIndex, THTTPHdrVal& aParamVal, const TStringTable& aTable ) const |
|
660 { |
|
661 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::GetParamValue"))); |
|
662 CRequest& request = const_cast < CRequest& > ( aRequest ); |
|
663 RRequest req = request.Handle (); |
|
664 RHTTPHeaders headers = req.GetHeaderCollection (); |
|
665 RStringF fieldStr = aRequest.StringPool ().StringF ( aFieldIndex, aTable ); |
|
666 RStringF paramStr = aRequest.StringPool ().StringF ( aParamIndex, aTable ); |
|
667 TInt err = KErrNone; |
|
668 TInt fieldCount = 0; |
|
669 TRAP ( err, fieldCount = headers.FieldPartsL(fieldStr) ); |
|
670 while (fieldCount>0) |
|
671 { |
|
672 err = headers.GetParam ( fieldStr, paramStr, aParamVal, fieldCount-1 ); |
|
673 if(err == KErrNone ) |
|
674 break; |
|
675 fieldCount--; |
|
676 } |
|
677 return err; |
|
678 } |
|
679 |
|
680 TBool CHttpMUdpFlow::IsHeaderPresent ( const CRequest& aRequest , TInt aFieldIndex, const TStringTable& aTable ) const |
|
681 { |
|
682 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsHeaderPresent"))); |
|
683 THTTPHdrVal value; |
|
684 return GetHeaderValue ( aRequest, aFieldIndex, value, aTable ); |
|
685 } |
|
686 |
|
687 TBool CHttpMUdpFlow::IsValidCacheControlHeader ( const CRequest& aRequest ) const |
|
688 { |
|
689 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidCacheControlHeader"))); |
|
690 THTTPHdrVal value; |
|
691 return GetParamValue ( aRequest, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table()); |
|
692 } |
|
693 |
|
694 TBool CHttpMUdpFlow::IsValidManHeader ( const CRequest& aRequest ) const |
|
695 { |
|
696 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader"))); |
|
697 THTTPHdrVal value; |
|
698 TInt err = GetHeaderValue ( aRequest, UPnP::EMAN, value, TUPnPTable::Table() ); |
|
699 if ( ( err == KErrNone ) && ( value.StrF ().DesC ().Compare ( KSsdpDiscover ) == 0)) |
|
700 { |
|
701 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader - MAN header has a valid value"))); |
|
702 return ETrue; |
|
703 } |
|
704 LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader - MAN header does not have a valid value"))); |
|
705 return EFalse; |
|
706 } |
|
707 |
|
708 TBool CHttpMUdpFlow::IsValidHostHeader ( CRequest& aRequest ) const |
|
709 { |
|
710 // From UPnP Device Architecture 1.0 |
|
711 // Must be 239.255.255.250:1900. If the port number(:1900) is omitted,the receiver |
|
712 // should assume the default SSDP port number of 1900. |
|
713 _LIT8 ( KSsdpHost, "239.255.255.250" ); |
|
714 |
|
715 THTTPHdrVal value; |
|
716 TInt err = GetHeaderValue ( aRequest, HTTP::EHost, value, THTTPTable::Table () ); |
|
717 if ( err != KErrNone ) |
|
718 { |
|
719 return EFalse; |
|
720 } |
|
721 |
|
722 const TDesC8& host = value.StrF ().DesC (); |
|
723 TInt pos = host.Locate ( TChar (':') ); |
|
724 |
|
725 if ( pos != KErrNotFound ) |
|
726 { |
|
727 TPtrC8 ptrHost = host.Mid ( 0, pos ); |
|
728 if ( ptrHost.Compare ( KSsdpHost ) != 0 ) |
|
729 { |
|
730 return EFalse; |
|
731 } |
|
732 |
|
733 TPtrC8 ptrPort = host.Mid ( pos + 1 ); |
|
734 _LIT8 ( KSsdpPort, "1900" ); |
|
735 |
|
736 if ( ptrPort.Length () > 0 && ptrPort.Compare ( KSsdpPort ) != 0 ) |
|
737 { |
|
738 return EFalse; |
|
739 } |
|
740 |
|
741 return ETrue; |
|
742 } |
|
743 |
|
744 if ( host.Compare ( KSsdpHost ) != 0 ) |
|
745 { |
|
746 return EFalse; |
|
747 } |
|
748 |
|
749 return ETrue; |
|
750 } |
|
751 /* CreateTimerEntry : creates the deltatimer entry and sets it to iEntry |
|
752 @param aUri The uri whose timer entry has to be created |
|
753 */ |
|
754 void CHttpMUdpFlow::CreateTimerEntryL() |
|
755 { |
|
756 const TInt KMXValue = 120; |
|
757 TInt maxAge = 0; |
|
758 RStringF location; |
|
759 ReadRequestValues ( maxAge, location ); |
|
760 if ( maxAge > KMXValue ) |
|
761 maxAge = KMXValue; |
|
762 const TDesC8& uri = location.DesC(); |
|
763 for ( TInt i = 0; i < iSearchTargetArray.Count (); ++i ) |
|
764 { |
|
765 const CSearchTarget& target = *(iSearchTargetArray[i]); |
|
766 if ( target.Match ( uri ) != KErrNotFound ) |
|
767 { |
|
768 CCallbackArgument* callArgument =CCallbackArgument::NewL(this, iRecvElements[0]->Address () , iSearchTargetArray[i]); |
|
769 CleanupStack::PushL(callArgument); |
|
770 TCallBack callBack(HandleMSearchRequestL,callArgument); |
|
771 TDeltaTimerEntry* entry = new (ELeave) TDeltaTimerEntry ( callBack ); |
|
772 CTimerMappedUri* timerMappedUri = CTimerMappedUri::NewL(location.DesC(),entry,maxAge); |
|
773 iTimerMappedArray.AppendL(timerMappedUri); |
|
774 callArgument->SetTimerEntry( entry ); |
|
775 iCallbackArray.AppendL(callArgument); |
|
776 CleanupStack::Pop(); |
|
777 // queue up in deltatimer |
|
778 TInt time = AdjustedDelay(maxAge); |
|
779 TTimeIntervalMicroSeconds32 delay(time); |
|
780 iDeltaTimer->Queue(delay,*entry); |
|
781 } |
|
782 } |
|
783 } |
|
784 /* Used to calculate the time in microseconds to set the timer entry.Also a little |
|
785 of time is used extra to account for Intra process communication |
|
786 @param aTime The time for which the timer has to be set in seconds |
|
787 @return The actual time in microseconds |
|
788 */ |
|
789 TInt CHttpMUdpFlow::AdjustedDelay( TInt aTime ) |
|
790 { |
|
791 TInt newNum; |
|
792 TTime now; |
|
793 now.UniversalTime(); |
|
794 TInt64 randSeed = now.Int64(); |
|
795 newNum = static_cast<TInt>(Math::Rand(randSeed)%aTime); |
|
796 const TUint KIntTime = 1000000 ; |
|
797 newNum = newNum * KIntTime ; |
|
798 return newNum; |
|
799 } |
|
800 CCallbackArgument* CCallbackArgument::NewL(TAny* aThis ,const TAppProtAddr& aAddress , const CSearchTarget* aStTarget) |
|
801 { |
|
802 CCallbackArgument* callArgument = new (ELeave )CCallbackArgument(aThis, aAddress , aStTarget); |
|
803 return callArgument; |
|
804 } |
|
805 |