|
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 // @file |
|
15 // @internalComponent |
|
16 // |
|
17 // |
|
18 |
|
19 //System Includes |
|
20 #include <comms-infras/ss_nodeinterfaces.h> |
|
21 //#include <comms-infras/ss_nodemessages_controlprovider.h> |
|
22 #include <inetprottextutils.h> |
|
23 #include <uriutils.h> |
|
24 #include <http/thttptable.h> |
|
25 #include <httperr.h> |
|
26 #include <httpstringconstants.h> |
|
27 #include <stringpool.h> |
|
28 #include <http/framework/cheadercodecplugin.h> |
|
29 #include <upnp/tupnptable.h> |
|
30 #include <rmemchunk.h> |
|
31 |
|
32 //Local Includes |
|
33 #include "httpclientflow.h" |
|
34 #include "upnpserverconstants.h" |
|
35 #include "upnplog.h" |
|
36 #include "upnppint.h" |
|
37 #include "upnpmemoryutils.h" |
|
38 |
|
39 |
|
40 using namespace ESock; |
|
41 using namespace Messages; |
|
42 |
|
43 |
|
44 __FLOG_STMT(_LIT8(KComponent,"Flow");) |
|
45 const TUint KHttpDefaultPort = 80; |
|
46 _LIT8(KSlash, "/"); |
|
47 |
|
48 CHttpClientFlow* CHttpClientFlow::NewL ( CSubConnectionFlowFactoryBase& aFactory, |
|
49 CProtocolIntfBase* aProtocolIntf, |
|
50 const TNodeId& aSubConnId, |
|
51 const TAppProtAddr& aSockAddr ) |
|
52 { |
|
53 CHttpClientFlow* self = new ( ELeave ) CHttpClientFlow ( aFactory, aProtocolIntf, aSubConnId, aSockAddr ); |
|
54 CleanupStack::PushL ( self ); |
|
55 self->ConstructL( ); |
|
56 CleanupStack::Pop ( self ); |
|
57 return self; |
|
58 } |
|
59 |
|
60 |
|
61 CHttpClientFlow::CHttpClientFlow ( CSubConnectionFlowFactoryBase& aFactory, CProtocolIntfBase* aProtocolIntf, const TNodeId& aSubConnId, const TAppProtAddr& aSockAddr ) |
|
62 : CUPnPFlowBase ( aFactory, aProtocolIntf, EHttpClientFlow, aSubConnId ), |
|
63 iDCIdle ( EFalse ), iRemoteAddress ( aSockAddr.iAddr, aSockAddr.iPort ), iResponseCompleted ( EFalse ), iReadStreamStarted ( EFalse ) |
|
64 { |
|
65 LOG_NODE_CREATE(KESockFlowTag, CHttpClientFlow); |
|
66 } |
|
67 |
|
68 |
|
69 CHttpClientFlow::~CHttpClientFlow ( ) |
|
70 { |
|
71 iRemoteAddress.FillZ ( ); |
|
72 iRequestUri.Close ( ); |
|
73 iActionValue.Close ( ); |
|
74 for ( TInt idx = 0; idx < iTransactions->Count( ); idx++ ) |
|
75 { |
|
76 delete iTransactions->Get( idx ); |
|
77 } |
|
78 if ( !iBufChain.IsEmpty ( ) ) |
|
79 iBufChain.Free ( ); |
|
80 |
|
81 delete iCodec; |
|
82 iStringPool.Close(); |
|
83 // Note! delete client handler after cleanp of transactions, or else it will panic |
|
84 delete iClientHandler; |
|
85 delete iActionParser; |
|
86 |
|
87 iSubConnectionProvider.Close ( ); |
|
88 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("Destroyed CHttpClientFlow"))); |
|
89 LOG_NODE_DESTROY(KESockFlowTag, CHttpClientFlow); |
|
90 } |
|
91 |
|
92 void CHttpClientFlow::ConstructL ( ) |
|
93 { |
|
94 iClientHandler = CHTTPClientHandler::NewL ( *this, static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager(), &iRemoteAddress ); |
|
95 iTransactions = iClientHandler->GetTransactionWrapperL( ); |
|
96 |
|
97 iStringPool.OpenL( TUPnPTable::Table() ); |
|
98 iStringPool.OpenL(THTTPTable::Table()); |
|
99 iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool ); |
|
100 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("Created CHttpClientFlow"))); |
|
101 } |
|
102 |
|
103 |
|
104 |
|
105 //From CSubConnectionFlowBase MNode |
|
106 void CHttpClientFlow::ReceivedL ( const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage ) |
|
107 { |
|
108 if ( aMessage.IsMessage<TEChild::TDestroy> () ) |
|
109 { |
|
110 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDestroy"))); |
|
111 if ( RemoveControlClient ( FindControlClient ( address_cast<TNodeId> ( aSender ) ) ) == 0 ) |
|
112 { |
|
113 DeleteThisFlow ( ); |
|
114 } |
|
115 } |
|
116 else if ( aMessage.IsMessage<TCFDataClient::TStart> () ) |
|
117 { |
|
118 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDataClientStart"))); |
|
119 RClientInterface::OpenPostMessageClose ( NodeId (), address_cast<TNodeCtxId> ( aSender ), TCFDataClient::TStarted ().CRef () ); |
|
120 } |
|
121 else if ( aMessage.IsMessage<TCFDataClient::TStop> () ) |
|
122 { |
|
123 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDataClientStop"))); |
|
124 CancelRequest ( address_cast<TNodeCtxId> ( aSender ) ); |
|
125 } |
|
126 else if ( aMessage.IsMessage<TUpnpMessage::TUPnPClientRequestInfo> () ) |
|
127 { |
|
128 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TUpnpMessage::TUPnPClientRequestInfo"))); |
|
129 TUpnpMessage::TUPnPClientRequestInfo& clntReqInfo = message_cast<TUpnpMessage::TUPnPClientRequestInfo> ( aMessage ); |
|
130 PrepareAndSubmitTransactionL ( clntReqInfo, address_cast<TNodeCtxId> ( aSender ) ); |
|
131 } |
|
132 } |
|
133 |
|
134 void CHttpClientFlow::CancelRequest ( TNodeCtxId aChannelId ) |
|
135 { |
|
136 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::CancelRequest"))); |
|
137 TInt pos = FindTransaction ( aChannelId ); |
|
138 if ( pos != KErrNotFound ) // transaction is not found |
|
139 { |
|
140 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::CancelRequest - Cancelling transaction"))); |
|
141 CTransaction* ctrans = iTransactions->Get( pos ); |
|
142 iClientHandler->CancelTransaction ( ctrans ); |
|
143 |
|
144 THTTPEvent event ( THTTPEvent::ECancel ); |
|
145 OnHttpEvent ( ctrans, event ); |
|
146 } |
|
147 else |
|
148 { |
|
149 if ( !iDCIdle ) // This will make sure when ASocket attached as upperflow |
|
150 // and unbind is received from it, No more communication will |
|
151 // happen to SCPR. |
|
152 { |
|
153 RClientInterface::OpenPostMessageClose ( NodeId (), aChannelId, TCFDataClient::TStopped ( 0 ).CRef () ); |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 |
|
159 TInt CHttpClientFlow::FindTransaction ( TNodeCtxId aChannelId ) |
|
160 { |
|
161 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction"))); |
|
162 TUint count = iTransactions->Count( ); |
|
163 for ( TInt idx = 0; idx < count; idx++ ) |
|
164 { |
|
165 CHTTPClientTransaction* ctrans = iTransactions->Get( idx ); |
|
166 |
|
167 if ( ctrans->NodeCtxId ( ) == aChannelId ) |
|
168 { |
|
169 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction - Transaction found at index %d"), idx)); |
|
170 return idx; |
|
171 } |
|
172 } |
|
173 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction - Transaction not found"))); |
|
174 return KErrNotFound; |
|
175 } |
|
176 |
|
177 void CHttpClientFlow::PrepareAndSubmitTransactionL ( RMBufChain& aData ) |
|
178 { |
|
179 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL"))); |
|
180 |
|
181 TNodeCtxId channelId ( MeshMachine::KActivityNull, NodeId () ); |
|
182 |
|
183 CHTTPClientTransaction* ctrans = CHTTPClientTransaction::NewL ( *iCodec, iStringPool, channelId ); |
|
184 iTransactions->AppendL ( ctrans ); |
|
185 |
|
186 CRequest* crequest = ctrans->Request( ); |
|
187 RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( ); |
|
188 RRequest rrequest = crequest->Handle( ); |
|
189 |
|
190 // Set request method |
|
191 RStringF stringF = iStringPool.StringF ( HTTP::EPOST, THTTPTable::Table() ); |
|
192 rrequest.SetMethod ( stringF ); |
|
193 |
|
194 // Set request Uri |
|
195 SetRequestUriL ( ctrans, iRequestUri ); |
|
196 SetContentTypeHeaderL ( headers ); |
|
197 |
|
198 //Set Content Length |
|
199 THTTPHdrVal hdrVal ( iOverallDataSize ); |
|
200 headers.SetFieldL ( iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ), hdrVal ); |
|
201 |
|
202 // Note! 100-continue, UPnP is not having any usecase to use this |
|
203 |
|
204 //Set Soap Action |
|
205 if ( SetActionHeaderL ( aData ) ) |
|
206 { |
|
207 // Complete headers are available, so Transaction is ready for submission |
|
208 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Submitting transaction"))); |
|
209 iClientHandler->SubmitTransaction( ctrans ); |
|
210 } |
|
211 |
|
212 // Set Body Data |
|
213 ctrans->AddBodyPart( aData ); |
|
214 SetTransactionComplete ( ctrans ); |
|
215 } |
|
216 |
|
217 TBool CHttpClientFlow::SetActionHeaderL ( RMBufChain& aData ) |
|
218 { |
|
219 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetActionHeaderL"))); |
|
220 |
|
221 CTransaction* ctrans = iTransactions->Get( 0 ); |
|
222 |
|
223 CRequest* crequest = ctrans->Request( ); |
|
224 RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( ); |
|
225 RRequest rrequest = crequest->Handle( ); |
|
226 |
|
227 // get service name & action name |
|
228 ConstructSoapActionHeaderValueL ( aData ); |
|
229 |
|
230 if ( iActionValue.Length ( ) != 0 ) |
|
231 { |
|
232 RStringF stringF = iStringPool.StringF ( UPnP::ESoapAction, TUPnPTable::Table() ); |
|
233 headers.SetRawFieldL ( stringF, iActionValue, KSoapFieldSeparator ); |
|
234 } |
|
235 |
|
236 return iActionValue.Length ( ) > 0; |
|
237 } |
|
238 |
|
239 void CHttpClientFlow::ConstructSoapActionHeaderValueL ( RMBufChain& aData ) |
|
240 { |
|
241 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ConstructSoapActionHeaderValueL"))); |
|
242 |
|
243 if ( iActionParser == NULL ) |
|
244 { |
|
245 iActionParser = CSoapParser::NewL ( ); |
|
246 } |
|
247 |
|
248 RBuf8 xmlData; |
|
249 xmlData.CreateMaxL ( aData.Length ( ) ); |
|
250 aData.CopyOut ( xmlData ); |
|
251 CleanupClosePushL ( xmlData ); |
|
252 |
|
253 if ( iActionParser->ParseSoapL( xmlData ) ) |
|
254 { |
|
255 TInt len = iActionParser->SoapAction( ).Length ( ) + KColon ( ).Length ( ) * 2; |
|
256 |
|
257 iActionValue.CreateL ( len ); |
|
258 |
|
259 iActionValue.Copy ( KColon ); |
|
260 iActionValue.Append ( iActionParser->SoapAction( ) ); |
|
261 iActionValue.Append ( KColon ); |
|
262 |
|
263 delete iActionParser; |
|
264 iActionParser = NULL; |
|
265 } |
|
266 |
|
267 CleanupStack::PopAndDestroy ( &xmlData ); |
|
268 } |
|
269 |
|
270 void CHttpClientFlow::SetContentTypeHeaderL ( RHTTPHeaders aHeaders ) |
|
271 { |
|
272 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetContentTypeHeaderL"))); |
|
273 // Set content-type |
|
274 RStringF stringF = iStringPool.StringF ( HTTP::EContentType, THTTPTable::Table() ); |
|
275 THTTPHdrVal contentTypeHdrVal; |
|
276 RStringF contentTypeHdr = iStringPool.StringF ( UPnP::ETextXml, TUPnPTable::Table() ); |
|
277 contentTypeHdrVal.SetStrF ( contentTypeHdr ); |
|
278 |
|
279 RStringF paramStringF = iStringPool.StringF ( HTTP::ECharset, THTTPTable::Table() ); |
|
280 THTTPHdrVal contentTypeParamVal; |
|
281 RStringF contentTypeParam = iStringPool.StringF ( UPnP::EUtf8, TUPnPTable::Table() ); |
|
282 contentTypeParamVal.SetStrF ( contentTypeParam ); |
|
283 aHeaders.SetFieldL ( stringF, contentTypeHdrVal, paramStringF, contentTypeParamVal ); |
|
284 } |
|
285 |
|
286 void CHttpClientFlow::ReSubmitTransactionL ( CTransaction* aTransaction ) |
|
287 { |
|
288 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReSubmitTransactionL"))); |
|
289 CRequest* crequest = aTransaction->Request( ); |
|
290 RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( ); |
|
291 RRequest rrequest = crequest->Handle ( ); |
|
292 |
|
293 // Set request method |
|
294 RStringF stringF = iStringPool.StringF ( UPnP::EMPost, TUPnPTable::Table() ); |
|
295 rrequest.SetMethod ( stringF ); |
|
296 |
|
297 // Set MAN Header |
|
298 stringF = iStringPool.StringF ( UPnP::EMAN, TUPnPTable::Table() ); |
|
299 THTTPHdrVal manHdrVal; |
|
300 RStringF manHdr = iStringPool.StringF ( UPnP::ESoapUrl, TUPnPTable::Table() ); |
|
301 manHdrVal.SetStrF ( manHdr ); |
|
302 |
|
303 RStringF paramStringF = iStringPool.StringF ( UPnP::ENS, TUPnPTable::Table() ); |
|
304 THTTPHdrVal nsParamVal; |
|
305 RStringF nsParam = iStringPool.StringF ( UPnP::ENsParam, TUPnPTable::Table() ); |
|
306 headers.SetFieldL ( stringF, manHdrVal, paramStringF, nsParamVal ); |
|
307 |
|
308 // recompose by adding '01' for SOAPACTION |
|
309 // remove existing soap header |
|
310 headers.RemoveField ( iStringPool.StringF ( UPnP::ESoapAction, TUPnPTable::Table() ) ); |
|
311 |
|
312 RStringF soapHdr = iStringPool.StringF ( UPnP::ESoapHeader, TUPnPTable::Table() ); |
|
313 |
|
314 // get service name & action name |
|
315 headers.SetRawFieldL ( soapHdr, iActionValue, KSoapFieldSeparator ); |
|
316 |
|
317 // Transaction is ready for submission. |
|
318 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReSubmitTransactionL - Submitting transaction"))); |
|
319 iClientHandler->SubmitTransaction( aTransaction ); |
|
320 } |
|
321 |
|
322 void CHttpClientFlow::PrepareAndSubmitTransactionL ( TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo, TNodeCtxId aChannelId ) |
|
323 { |
|
324 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL"))); |
|
325 CHTTPClientTransaction* ctrans = CHTTPClientTransaction::NewL ( *iCodec, iStringPool, aChannelId ); |
|
326 CleanupStack::PushL ( ctrans ); |
|
327 |
|
328 RBuf8 uriBuf; |
|
329 uriBuf.CreateMax( aClntReqInfo.iUri.Length( ) ); |
|
330 CleanupClosePushL( uriBuf ); |
|
331 uriBuf.FillZ( aClntReqInfo.iUri.Length( ) ); |
|
332 aClntReqInfo.iUri.CopyOut( uriBuf ); |
|
333 aClntReqInfo.iUri.Free( ); |
|
334 // Extract the uri path from the absolute uri and set the request uri |
|
335 SetRequestUriL ( ctrans, uriBuf ); |
|
336 CleanupStack::PopAndDestroy( &uriBuf ); |
|
337 |
|
338 RRequest rrequest = ctrans->Request( )->Handle( ); |
|
339 RStringF method; |
|
340 RStringF contentLenStrF = iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ); |
|
341 THTTPHdrVal contentLenVal; |
|
342 TInt contentLength = 0; |
|
343 contentLenVal.SetInt( contentLength ); |
|
344 switch ( aClntReqInfo.iRequestMethod ) |
|
345 { |
|
346 case HTTP::EGET: |
|
347 { |
|
348 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling describe(GET) request"))); |
|
349 method = iStringPool.StringF ( HTTP::EGET, THTTPTable::Table() ); |
|
350 rrequest.SetMethod ( method ); |
|
351 } |
|
352 break; |
|
353 |
|
354 case UPnP::ESubscribe: |
|
355 { |
|
356 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling SUBSCRIBE request"))); |
|
357 method = iStringPool.StringF ( UPnP::ESubscribe, TUPnPTable::Table() ); |
|
358 rrequest.SetMethod ( method ); |
|
359 BuildSubscribeRequestL ( *(ctrans->Request()), aClntReqInfo ); |
|
360 } |
|
361 break; |
|
362 |
|
363 case UPnP::EUnsubscribe: |
|
364 { |
|
365 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling UNSUBSCRIBE request"))); |
|
366 method = iStringPool.StringF ( UPnP::EUnsubscribe, TUPnPTable::Table() ); |
|
367 rrequest.SetMethod ( method ); |
|
368 SetSidHeaderL ( *(ctrans->Request()), aClntReqInfo ); |
|
369 } |
|
370 break; |
|
371 |
|
372 case UPnP::ENotify: |
|
373 { |
|
374 RMBufChain bufChain; |
|
375 TUPnPMemoryUtils::CreateMBuf(bufChain, aClntReqInfo.iBody ); |
|
376 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling NOTIFY request"))); |
|
377 method = iStringPool.StringF ( UPnP::ENotify, TUPnPTable::Table() ); |
|
378 rrequest.SetMethod ( method ); |
|
379 BuildNotifyRequestL ( *(ctrans->Request()), aClntReqInfo ); |
|
380 // set body |
|
381 contentLength = aClntReqInfo.iBody.Length ( ); |
|
382 contentLenVal.SetInt( contentLength ); |
|
383 ctrans->AddBodyPart( bufChain ); |
|
384 aClntReqInfo.iBody.Free(); |
|
385 } |
|
386 break; |
|
387 |
|
388 default: |
|
389 break; |
|
390 } |
|
391 |
|
392 CleanupStack::Pop ( ); |
|
393 |
|
394 rrequest.GetHeaderCollection ( ).SetFieldL ( contentLenStrF, contentLenVal ); |
|
395 // Transaction is ready for submission. |
|
396 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Submitting transaction"))); |
|
397 ctrans->SetComplete (); |
|
398 iClientHandler->SubmitTransaction( ctrans ); |
|
399 } |
|
400 |
|
401 void CHttpClientFlow::SetRequestUriL ( CTransaction* aTrans, const TDesC8& aUri ) |
|
402 { |
|
403 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL"))); |
|
404 RRequest rrequest = aTrans->Request( )->Handle( ); |
|
405 TUriParser8 uri; |
|
406 uri.Parse ( aUri ); |
|
407 TPtrC8 ptr; |
|
408 ptr.Set(uri.UriDes()); |
|
409 ptr.Set(ptr.Mid(ptr.Find(_L8("//")) + 2)); |
|
410 TInt pos = ptr.Locate('/'); |
|
411 if(pos == KErrNotFound) |
|
412 { |
|
413 ptr.Set(KSlash()); |
|
414 } |
|
415 else |
|
416 { |
|
417 ptr.Set(ptr.Mid(pos)); |
|
418 } |
|
419 |
|
420 TUriParser8 uriPath; |
|
421 uriPath.Parse(ptr); |
|
422 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Setting the URI"))); |
|
423 rrequest.SetURIL ( uriPath ); |
|
424 |
|
425 |
|
426 // Set Host Header |
|
427 TInt port; |
|
428 if ( uri.IsPresent ( EUriPort ) ) |
|
429 { |
|
430 const TDesC8& portStr = uri.Extract ( EUriPort ); |
|
431 InetProtTextUtils::ConvertDescriptorToInt ( portStr, port ); |
|
432 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Got the port from URI %d"), port)); |
|
433 } |
|
434 else |
|
435 { |
|
436 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Using default HTTP port 80"))); |
|
437 port = KHttpDefaultPort; |
|
438 } |
|
439 |
|
440 SetHostHeaderL ( aTrans, uri.Extract ( EUriHost ), port ); |
|
441 } |
|
442 |
|
443 void CHttpClientFlow::SetHostHeaderL ( CTransaction* aTrans, const TDesC8& aHost, TInt aPort ) |
|
444 { |
|
445 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetHostHeaderL"))); |
|
446 RStringF hostStr = iStringPool.StringF ( HTTP::EHost, THTTPTable::Table() ); |
|
447 RRequest request = aTrans->Request( )->Handle( ); |
|
448 RHTTPHeaders headers = request.GetHeaderCollection(); |
|
449 |
|
450 //If the Host header does not already exist, add it! |
|
451 THTTPHdrVal hostValue; |
|
452 if ( headers.GetField ( hostStr, 0, hostValue ) == KErrNotFound ) |
|
453 { |
|
454 // Set the Host header... |
|
455 RStringF hostValStr; |
|
456 // Check if its a literal IPV6 address |
|
457 UriUtils::TUriHostType aHostsType = UriUtils::HostType ( aHost ); |
|
458 if ( ( aHostsType != UriUtils::ETextHost ) && ( aHostsType != UriUtils::EIPv4Host ) ) // is an IPv6 or other future protocol address |
|
459 { |
|
460 HBufC8* ipv6LiteralHost = HBufC8::NewLC ( aHost.Length() + 2 ); // add 2 for the braces |
|
461 |
|
462 TPtr8 ipv6LiteralHostPtr = ipv6LiteralHost->Des(); |
|
463 |
|
464 ipv6LiteralHostPtr.Append ( KIPv6HostOpenBrace ); |
|
465 ipv6LiteralHostPtr.Append ( aHost ); |
|
466 ipv6LiteralHostPtr.Append ( KIPv6HostCloseBrace ); |
|
467 |
|
468 hostValStr = iStringPool.OpenFStringL( ipv6LiteralHostPtr ); |
|
469 CleanupStack::PopAndDestroy( ipv6LiteralHost ); |
|
470 } |
|
471 else |
|
472 { |
|
473 hostValStr = iStringPool.OpenFStringL( aHost ); |
|
474 } |
|
475 |
|
476 CleanupClosePushL ( hostValStr ); |
|
477 |
|
478 THTTPHdrVal hostVal ( hostValStr ); |
|
479 headers.SetFieldL ( hostStr, hostVal ); |
|
480 CleanupStack::PopAndDestroy ( &hostValStr ); |
|
481 |
|
482 // Also set the port number if Host header is not empty and a port |
|
483 // number is not the default. |
|
484 if ( aPort != KHttpDefaultPort ) |
|
485 { |
|
486 THTTPHdrVal portVal ( aPort ); |
|
487 RStringF portStr = iStringPool.StringF ( HTTP::EPort,THTTPTable::Table() ); |
|
488 headers.SetParamL ( hostStr, portStr, portVal, 0 ); |
|
489 } |
|
490 } |
|
491 } |
|
492 |
|
493 void CHttpClientFlow::BuildSubscribeRequestL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo ) |
|
494 { |
|
495 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BuildSubscribeRequestL"))); |
|
496 TSubscribeRequestInfo& info = *( reinterpret_cast < TSubscribeRequestInfo* > ( aClntReqInfo.iInfo ) ); |
|
497 RStringF strF = iStringPool.StringF ( UPnP::ETimeout, TUPnPTable::Table() ); |
|
498 if(info.iTimeOut != 0) |
|
499 { |
|
500 THTTPHdrVal hTimeOutVal(info.iTimeOut); |
|
501 aNewRequest.Handle().GetHeaderCollection().SetFieldL ( strF, hTimeOutVal ); |
|
502 } |
|
503 |
|
504 strF = iStringPool.StringF ( UPnP::ECallback, TUPnPTable::Table() ); |
|
505 THTTPHdrVal hCallbackVal; |
|
506 |
|
507 if ( info.iCallback.Length() > 0 ) |
|
508 { |
|
509 RBuf8 callbackBuf; |
|
510 callbackBuf.CreateMax ( info.iCallback.Length( ) ); |
|
511 CleanupClosePushL ( callbackBuf ); |
|
512 callbackBuf.FillZ ( info.iCallback.Length( ) ); |
|
513 info.iCallback.CopyOut ( callbackBuf ); |
|
514 info.iCallback.Free ( ); |
|
515 |
|
516 RStringF callbackStrF = iStringPool.OpenFStringL ( callbackBuf ); |
|
517 CleanupClosePushL ( callbackStrF ); |
|
518 hCallbackVal.SetStrF (callbackStrF ); |
|
519 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hCallbackVal ); |
|
520 CleanupStack::PopAndDestroy ( &callbackStrF ); |
|
521 CleanupStack::PopAndDestroy ( &callbackBuf ); |
|
522 SetNtHeaderL ( aNewRequest.Handle ( ).GetHeaderCollection ( ) ); |
|
523 } |
|
524 else |
|
525 { |
|
526 SetSidHeaderL ( aNewRequest, aClntReqInfo ); |
|
527 } |
|
528 } |
|
529 |
|
530 void CHttpClientFlow::SetSidHeaderL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo ) |
|
531 { |
|
532 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetSidHeaderL"))); |
|
533 if( aClntReqInfo.iRequestMethod == UPnP::ESubscribe || aClntReqInfo.iRequestMethod == UPnP::EUnsubscribe ) |
|
534 { |
|
535 TSubscribeRequestInfo& info = *( reinterpret_cast < TSubscribeRequestInfo* > ( aClntReqInfo.iInfo ) ); |
|
536 RStringF strF = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() ); |
|
537 THTTPHdrVal hSidVal; |
|
538 |
|
539 RBuf8 sidBuf; |
|
540 sidBuf.CreateMax ( info.iSid.Length( ) ); |
|
541 CleanupClosePushL ( sidBuf ); |
|
542 sidBuf.FillZ ( info.iSid.Length( ) ); |
|
543 info.iSid.CopyOut( sidBuf ); |
|
544 //info.iSid.Free ( ); |
|
545 info.iSid.Init(); |
|
546 TPtrC8 asdf(sidBuf); |
|
547 RStringF sidValStrF = iStringPool.OpenFStringL( sidBuf ); |
|
548 CleanupClosePushL ( sidValStrF ); |
|
549 hSidVal.SetStrF ( sidValStrF ); |
|
550 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSidVal ); |
|
551 CleanupStack::PopAndDestroy ( &sidValStrF ); |
|
552 CleanupStack::PopAndDestroy ( &sidBuf ); |
|
553 } |
|
554 else if ( aClntReqInfo.iRequestMethod == UPnP::ENotify ) |
|
555 { |
|
556 TEventNotifyRequestInfo& info = *( reinterpret_cast < TEventNotifyRequestInfo* > ( aClntReqInfo.iInfo ) ); |
|
557 RStringF strF = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() ); |
|
558 THTTPHdrVal hSidVal; |
|
559 |
|
560 RBuf8 sidBuf; |
|
561 sidBuf.CreateMax ( info.iSid.Length( ) ); |
|
562 CleanupClosePushL ( sidBuf ); |
|
563 sidBuf.FillZ ( info.iSid.Length( ) ); |
|
564 info.iSid.CopyOut( sidBuf ); |
|
565 //info.iSid.Free ( ); |
|
566 info.iSid.Init(); |
|
567 RStringF sidValStrF = iStringPool.OpenFStringL( sidBuf ); |
|
568 CleanupClosePushL ( sidValStrF ); |
|
569 hSidVal.SetStrF ( sidValStrF ); |
|
570 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSidVal ); |
|
571 CleanupStack::PopAndDestroy ( &sidValStrF ); |
|
572 CleanupStack::PopAndDestroy ( &sidBuf ); |
|
573 } |
|
574 } |
|
575 |
|
576 void CHttpClientFlow::BuildNotifyRequestL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo ) |
|
577 { |
|
578 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BuildNotifyRequestL"))); |
|
579 TEventNotifyRequestInfo& info = *( reinterpret_cast < TEventNotifyRequestInfo* > ( aClntReqInfo.iInfo ) ); |
|
580 SetSidHeaderL ( aNewRequest, aClntReqInfo ); |
|
581 SetNtHeaderL ( aNewRequest.Handle ( ).GetHeaderCollection ( ) ); |
|
582 |
|
583 RStringF strF = iStringPool.StringF ( UPnP::ESEQ, TUPnPTable::Table() ); |
|
584 THTTPHdrVal hSeqVal( info.iSeqKey ); |
|
585 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSeqVal ); |
|
586 |
|
587 strF = iStringPool.StringF ( UPnP::ENTS, TUPnPTable::Table() ); |
|
588 RStringF ntsValStrF = iStringPool.StringF ( UPnP::EUpnpPropChange, TUPnPTable::Table() ); |
|
589 THTTPHdrVal hNtsVal; |
|
590 hNtsVal.SetStrF ( ntsValStrF ); |
|
591 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hNtsVal ); |
|
592 |
|
593 // Set content-type |
|
594 strF = iStringPool.StringF ( HTTP::EContentType, THTTPTable::Table() ); |
|
595 RStringF contentTypeStrF = iStringPool.StringF( UPnP::ETextXml, TUPnPTable::Table() ); |
|
596 THTTPHdrVal hContentTypeVal; |
|
597 hContentTypeVal.SetStrF ( contentTypeStrF ); |
|
598 aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hContentTypeVal ); |
|
599 } |
|
600 |
|
601 void CHttpClientFlow::SetNtHeaderL ( RHTTPHeaders aHeaders ) |
|
602 { |
|
603 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetNtHeaderL"))); |
|
604 RStringF strF = iStringPool.StringF ( UPnP::ENT, TUPnPTable::Table() ); |
|
605 RStringF ntValStrF = iStringPool.StringF ( UPnP::EUpnpEvent, TUPnPTable::Table() ); |
|
606 CleanupClosePushL ( ntValStrF ); |
|
607 THTTPHdrVal hNtVal; |
|
608 hNtVal.SetStrF ( ntValStrF ); |
|
609 aHeaders.SetFieldL ( strF, hNtVal ); |
|
610 CleanupStack::PopAndDestroy ( &ntValStrF ); |
|
611 } |
|
612 |
|
613 |
|
614 MFlowBinderControl* CHttpClientFlow::DoGetBinderControlL ( ) |
|
615 { |
|
616 return this; |
|
617 } |
|
618 |
|
619 // MFlowBinderControl |
|
620 CSubConnectionFlowBase* CHttpClientFlow::Flow ( ) |
|
621 { |
|
622 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Flow"))); |
|
623 return this; |
|
624 } |
|
625 |
|
626 MSessionControl* CHttpClientFlow::GetControlL ( TInt /*aSessionType*/, MSessionControlNotify& aSessionControlNotify ) |
|
627 { |
|
628 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetControlL"))); |
|
629 ASSERT ( iSessionControlNotify == NULL ); |
|
630 iSessionControlNotify = &aSessionControlNotify; |
|
631 |
|
632 return this; |
|
633 } |
|
634 |
|
635 MSessionData* CHttpClientFlow::BindL ( MSessionDataNotify& aNotify ) |
|
636 { |
|
637 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BindL"))); |
|
638 ASSERT ( iSessionDataNotify == NULL ); |
|
639 iSessionDataNotify = &aNotify; |
|
640 iSubConnectionProvider.PostMessage ( Id (), TCFControlProvider::TActive ().CRef () ); |
|
641 return this; |
|
642 } |
|
643 |
|
644 void CHttpClientFlow::Unbind ( ) |
|
645 { |
|
646 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Unbind"))); |
|
647 iSessionControlNotify = NULL; |
|
648 iSessionDataNotify = NULL; |
|
649 iDCIdle = ETrue; |
|
650 if ( iSubConnectionProvider.IsOpen ( ) ) |
|
651 { |
|
652 iSubConnectionProvider.PostMessage ( Id (), TCFControlProvider::TIdle ().CRef () ); |
|
653 } |
|
654 } |
|
655 |
|
656 // MSessionControl |
|
657 void CHttpClientFlow::Shutdown ( MSessionControl::TCloseType aOption ) |
|
658 { |
|
659 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Shutdown"))); |
|
660 if ( MSessionControl::ENormal == aOption) |
|
661 iSessionControlNotify->CanClose( MSessionControlNotify::EDelete); |
|
662 } |
|
663 |
|
664 void CHttpClientFlow::ActiveOpen ( ) |
|
665 { |
|
666 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ActiveOpen"))); |
|
667 iSessionControlNotify->ConnectComplete ( ); |
|
668 } |
|
669 |
|
670 TInt CHttpClientFlow::SetRemName ( TSockAddr& anAddr ) |
|
671 { |
|
672 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRemName"))); |
|
673 iRemoteAddress = anAddr; |
|
674 iClientHandler->SetConnectionInfo ( iRemoteAddress ); |
|
675 return KErrNone; |
|
676 } |
|
677 |
|
678 TInt CHttpClientFlow::GetOption ( TUint aLevel, TUint aName, TDes8& anOption ) const |
|
679 { |
|
680 if ( aLevel == KCHOptionLevel ) |
|
681 { |
|
682 switch ( aName ) |
|
683 { |
|
684 case KCHMaxLength: |
|
685 { |
|
686 *(TUint*) anOption.Ptr() = iOverallDataSize; |
|
687 } |
|
688 break; |
|
689 |
|
690 case KCHLastMessage: |
|
691 { |
|
692 *(TUint*) anOption.Ptr() = ( iResponseCompleted && iBufChain.Length () == 0 ); |
|
693 } |
|
694 break; |
|
695 |
|
696 default: |
|
697 { |
|
698 ASSERT ( 0 ); |
|
699 } |
|
700 break; |
|
701 } |
|
702 } |
|
703 |
|
704 return KErrNone; |
|
705 } |
|
706 |
|
707 TInt CHttpClientFlow::SetOption (TUint aLevel, TUint aName, const TDesC8& anOption) |
|
708 { |
|
709 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetOption"))); |
|
710 |
|
711 TInt err = KErrNone; |
|
712 if ( aLevel == KCHOptionLevel ) |
|
713 { |
|
714 switch ( aName ) |
|
715 { |
|
716 case KCHAbsoluteUri: |
|
717 { |
|
718 err = iRequestUri.Create ( anOption ); |
|
719 } |
|
720 break; |
|
721 |
|
722 case KCHMaxLength: |
|
723 { |
|
724 TPckgBuf <TCHMessageOption> option; |
|
725 option.Copy ( anOption ); |
|
726 |
|
727 iChannelIdentifier = option ( ).iId; |
|
728 iOverallDataSize = option ( ).iValue; |
|
729 } |
|
730 break; |
|
731 |
|
732 default: |
|
733 { |
|
734 ASSERT ( 0 ); |
|
735 } |
|
736 break; |
|
737 } |
|
738 } |
|
739 |
|
740 return err; |
|
741 } |
|
742 |
|
743 TInt CHttpClientFlow::Write ( RMBufChain& aData, TUint /*aOptions*/, TSockAddr* /*anAddr*/ ) |
|
744 { |
|
745 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write"))); |
|
746 |
|
747 // Note!..http client flow of upnp stack doesn't |
|
748 // supports HTTP chunked encoding for sending request body |
|
749 |
|
750 __ASSERT_DEBUG ( iOverallDataSize != KErrUnknown, User::Invariant () ); |
|
751 |
|
752 TInt len = aData.Length ( ); |
|
753 |
|
754 if ( iTransactions->Count( ) == 0 ) |
|
755 { |
|
756 TRAP ( iError, PrepareAndSubmitTransactionL ( aData ) ); |
|
757 if ( iError != KErrNone ) |
|
758 { |
|
759 if ( !aData.IsEmpty() ) |
|
760 aData.Free ( ); |
|
761 DoReset ( ); |
|
762 return iError; |
|
763 } |
|
764 } |
|
765 else |
|
766 { |
|
767 CTransaction* ctrans = iTransactions->Get( 0 ); |
|
768 |
|
769 if ( iActionValue.Length ( ) == 0 ) |
|
770 { |
|
771 TBool doSubmit = EFalse; |
|
772 TRAP ( iError, doSubmit = SetActionHeaderL ( aData ) ); |
|
773 |
|
774 // Append body parts |
|
775 ctrans->AddBodyPart ( aData ); |
|
776 |
|
777 if ( iError == KErrNone ) |
|
778 { |
|
779 // transaction is waiting for more data to build soap action header |
|
780 if ( doSubmit ) |
|
781 { |
|
782 // Complete headers are available, so Transaction is ready for submission |
|
783 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write - Submitting transaction"))); |
|
784 iClientHandler->SubmitTransaction( ctrans ); |
|
785 } |
|
786 } |
|
787 else |
|
788 { |
|
789 DoReset ( ); |
|
790 return iError; |
|
791 } |
|
792 } |
|
793 else |
|
794 { |
|
795 // transaction is waiting for more request body data |
|
796 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write - Notfiy new request body parts"))); |
|
797 iClientHandler->NotifyNewRequestBodyData ( ctrans, aData ); |
|
798 } |
|
799 SetTransactionComplete ( ctrans ); |
|
800 } |
|
801 |
|
802 aData.Init ( ); |
|
803 return len; |
|
804 } |
|
805 |
|
806 TInt CHttpClientFlow::GetData ( RMBufChain& aData, TUint aLength, TUint /*aOptions*/, TSockAddr* /*anAddr*/ ) |
|
807 { |
|
808 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData"))); |
|
809 |
|
810 if ( iError < 0 ) |
|
811 { |
|
812 DoReset (); |
|
813 return iError; |
|
814 } |
|
815 |
|
816 if ( !iReadStreamStarted ) |
|
817 { |
|
818 TBuf8<sizeof ( TInt )> identifiersBuf; |
|
819 identifiersBuf.AppendNumFixedWidth ( iChannelIdentifier, EDecimal, sizeof ( TInt ) ); |
|
820 aData.Append ( identifiersBuf.Length () ); |
|
821 aData.CopyIn ( identifiersBuf ); |
|
822 iReadStreamStarted = ETrue; |
|
823 } |
|
824 else |
|
825 { |
|
826 RMBufChain newChain; |
|
827 iError = iBufChain.Split ( aLength, newChain ); |
|
828 if ( iError != KErrNone ) |
|
829 { |
|
830 DoReset (); |
|
831 return iError; |
|
832 } |
|
833 |
|
834 aData.Assign ( iBufChain ); |
|
835 iBufChain = newChain; |
|
836 } |
|
837 |
|
838 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData--Data Read by Upper flow--%d"), aData.Length ( ))); |
|
839 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData--Data left over--%d"), iBufChain.Length ( ))); |
|
840 |
|
841 return aData.Length ( ); |
|
842 } |
|
843 |
|
844 void CHttpClientFlow::SetTransactionComplete ( CTransaction* aTransaction ) |
|
845 { |
|
846 if ( iOverallDataSize == aTransaction->BodyParts ().Length () ) |
|
847 { |
|
848 aTransaction->SetComplete (); |
|
849 } |
|
850 } |
|
851 |
|
852 // MInputStreamObserver |
|
853 TInt CHttpClientFlow::OnHttpEvent ( CTransaction* aTransaction, THTTPEvent& aEvent ) |
|
854 { |
|
855 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent"))); |
|
856 CHTTPClientTransaction* clientTrans = static_cast<CHTTPClientTransaction*>( aTransaction ); |
|
857 |
|
858 // Process event for Control plane transaction |
|
859 TNodeCtxId selfCtx ( MeshMachine::KActivityNull, NodeId () ); |
|
860 if ( clientTrans->NodeCtxId () != selfCtx ) |
|
861 { |
|
862 ProcessControlPlaneResponseEvent ( clientTrans, aEvent ); |
|
863 return KErrNone; |
|
864 } |
|
865 |
|
866 // Process event for Socket Transaction |
|
867 TBool cleanupNeeded = EFalse; |
|
868 switch ( aEvent.iStatus ) |
|
869 { |
|
870 case THTTPEvent::EGotResponseHeaders: |
|
871 { |
|
872 RResponse response = clientTrans->Response( )->Handle( ); |
|
873 RHTTPHeaders headers = response.GetHeaderCollection ( ); |
|
874 |
|
875 RStringF fieldStr = iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table ( ) ); |
|
876 THTTPHdrVal value; |
|
877 |
|
878 if ( headers.GetField ( fieldStr, 0, value ) == KErrNotFound ) |
|
879 { |
|
880 iOverallDataSize = KErrUnknown; |
|
881 } |
|
882 else |
|
883 { |
|
884 iOverallDataSize = value.Int ( ); |
|
885 } |
|
886 } |
|
887 break; |
|
888 |
|
889 case THTTPEvent::EGotResponseBodyData: |
|
890 { |
|
891 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EGotResponseBodyData"))); |
|
892 |
|
893 TInt notifyLen = 0; |
|
894 FillResponseChain ( aTransaction, notifyLen ); |
|
895 iSessionDataNotify->NewData( notifyLen ); |
|
896 } |
|
897 break; |
|
898 |
|
899 case THTTPEvent::EResponseComplete: |
|
900 { |
|
901 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete"))); |
|
902 if ( clientTrans->Response( )->Status( ) == HTTPStatus::EMethodNotAllowed ) |
|
903 { |
|
904 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Response status = %d"), clientTrans->Response( )->Status( ))); |
|
905 |
|
906 clientTrans->SetComposingStarted ( EFalse ); |
|
907 clientTrans->ResetRequestPart (); |
|
908 TRAPD ( err, ReSubmitTransactionL ( clientTrans ) ); |
|
909 |
|
910 if ( err != KErrNone ) |
|
911 { |
|
912 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Error %d while re-submitting trans"), err)); |
|
913 cleanupNeeded = ETrue; |
|
914 NotifyError ( clientTrans, err ); |
|
915 } |
|
916 } |
|
917 else |
|
918 { |
|
919 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Response status = %d"), clientTrans->Response( )->Status( ))); |
|
920 |
|
921 iResponseCompleted = ETrue; |
|
922 cleanupNeeded = ETrue; |
|
923 iSessionDataNotify->NewData( sizeof ( TInt ) ); |
|
924 } |
|
925 } |
|
926 break; |
|
927 |
|
928 default: |
|
929 { |
|
930 if ( aEvent.iStatus < 0 ) |
|
931 { |
|
932 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - Error status = %d"), aEvent.iStatus)); |
|
933 NotifyError ( clientTrans, aEvent.iStatus ); |
|
934 } |
|
935 } |
|
936 break; |
|
937 } |
|
938 |
|
939 if ( cleanupNeeded ) |
|
940 { |
|
941 // body is processed completely, and clienthandler removed it from its array |
|
942 delete clientTrans; |
|
943 } |
|
944 return KErrNone; |
|
945 } |
|
946 |
|
947 void CHttpClientFlow::ProcessControlPlaneResponseEvent ( CHTTPClientTransaction* aTransaction, THTTPEvent& aEvent ) |
|
948 { |
|
949 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent"))); |
|
950 TBool iCleanupNeeded = EFalse; |
|
951 |
|
952 switch ( aEvent.iStatus ) |
|
953 { |
|
954 case THTTPEvent::ECancel: |
|
955 { |
|
956 // post complete message with KErrCancel |
|
957 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::ECancel"))); |
|
958 RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), TCFDataClient::TStopped ( 0 ).CRef () ); |
|
959 iCleanupNeeded = ETrue; |
|
960 } |
|
961 break; |
|
962 |
|
963 case THTTPEvent::EGotResponseBodyData: |
|
964 { |
|
965 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::EGotResponseBodyData"))); |
|
966 |
|
967 TInt notifyLen = 0; |
|
968 FillResponseChain ( aTransaction, notifyLen ); |
|
969 // Note! no need to process any body parts for control plane transaction |
|
970 } |
|
971 break; |
|
972 |
|
973 case THTTPEvent::EResponseComplete: |
|
974 { |
|
975 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::EResponseComplete"))); |
|
976 CResponse* cresponse = aTransaction->Response( ); |
|
977 RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager()); |
|
978 |
|
979 RMemChunk memChunk; |
|
980 TUPnPMemoryUtils::CreateMemChunk(memChunk, iBufChain, allocator ); |
|
981 |
|
982 // request method is subscribe |
|
983 if ( aTransaction->Request( )->Method( ).Index ( TUPnPTable::Table() ) |
|
984 == UPnP::ESubscribe ) |
|
985 { |
|
986 if(cresponse->Status() == HTTPStatus::EOk) |
|
987 { |
|
988 RHTTPHeaders headers = cresponse->Handle( ).GetHeaderCollection ( ); |
|
989 |
|
990 // Timeout field value |
|
991 RStringF fieldNameStr = iStringPool.StringF ( UPnP::ETimeout, TUPnPTable::Table() ); |
|
992 THTTPHdrVal timeOutVal; |
|
993 headers.GetField ( fieldNameStr, 0, timeOutVal ); |
|
994 TInt timeOut; |
|
995 if ( timeOutVal.Type ( ) == THTTPHdrVal::KNoType ) |
|
996 { |
|
997 RHTTPHeaders reqHds = aTransaction->Request( )->Handle( ).GetHeaderCollection ( ); |
|
998 reqHds.GetField ( fieldNameStr, 0, timeOutVal ); |
|
999 timeOut = timeOutVal.Int ( ); |
|
1000 } |
|
1001 else |
|
1002 { |
|
1003 timeOut = timeOutVal.Int ( ); |
|
1004 } |
|
1005 |
|
1006 // SID field value |
|
1007 fieldNameStr = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() ); |
|
1008 TPtrC8 rawValue; |
|
1009 headers.GetRawField ( fieldNameStr, rawValue ); |
|
1010 |
|
1011 RMemChunk sid; |
|
1012 sid.Create ( rawValue, allocator ); |
|
1013 |
|
1014 |
|
1015 TUpnpMessage::TSubscribeResponse msg ( cresponse->Status( ), |
|
1016 cresponse->Version( ), |
|
1017 memChunk, |
|
1018 timeOut, |
|
1019 sid ); |
|
1020 RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg ); |
|
1021 } |
|
1022 else |
|
1023 { |
|
1024 TEBase::TError msg ( TUpnpMessage::TUPnPClientRequestInfo::Id(), cresponse->Status() ); |
|
1025 RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg ); |
|
1026 } |
|
1027 } |
|
1028 else |
|
1029 { |
|
1030 TUpnpMessage::TResponse msg ( cresponse->Status( ), cresponse->Version( ), memChunk ); |
|
1031 RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg ); |
|
1032 } |
|
1033 iBufChain.Free ( ); |
|
1034 iCleanupNeeded = ETrue; |
|
1035 } |
|
1036 break; |
|
1037 |
|
1038 default: |
|
1039 { |
|
1040 if ( aEvent.iStatus < 0 ) |
|
1041 { |
|
1042 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - Error status = %d"), aEvent.iStatus)); |
|
1043 NotifyError ( aTransaction, aEvent.iStatus ); |
|
1044 iCleanupNeeded = ETrue; |
|
1045 } |
|
1046 } |
|
1047 break; |
|
1048 } |
|
1049 |
|
1050 if ( iCleanupNeeded ) |
|
1051 { |
|
1052 // Cleanup |
|
1053 delete aTransaction; |
|
1054 } |
|
1055 } |
|
1056 |
|
1057 void CHttpClientFlow::FillResponseChain ( CTransaction* aTransaction, TInt& aNewLen ) |
|
1058 { |
|
1059 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FillResponseChain"))); |
|
1060 MHTTPDataSupplier* bodySupplier = aTransaction->Response( )->Body( ); |
|
1061 TPtrC8 bodyPtr; |
|
1062 RMBufChain bodyChain; |
|
1063 |
|
1064 bodySupplier->GetNextDataPart ( bodyPtr ); |
|
1065 bodyChain.Create ( bodyPtr ); |
|
1066 iBufChain.Append ( bodyChain ); |
|
1067 |
|
1068 bodySupplier->ReleaseData( ); |
|
1069 |
|
1070 aNewLen = bodyPtr.Length ( ); |
|
1071 |
|
1072 LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FillResponseChain--chunk length from parser = %d"), aNewLen)); |
|
1073 } |
|
1074 |
|
1075 void CHttpClientFlow::NotifyError ( CHTTPClientTransaction* aTransaction, TInt aError ) |
|
1076 { |
|
1077 TNodeCtxId selfCtx ( MeshMachine::KActivityNull, NodeId () ); |
|
1078 if ( aTransaction->NodeCtxId () != selfCtx ) |
|
1079 { |
|
1080 // For SCPR Transactions post error response and cleanup |
|
1081 TEBase::TError msg ( TUpnpMessage::TUPnPClientRequestInfo::Id ( ), aError ); |
|
1082 RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg ); |
|
1083 } |
|
1084 else |
|
1085 { |
|
1086 // Handle error for socket transactions |
|
1087 iError = aError; |
|
1088 iResponseCompleted = ETrue; |
|
1089 iOverallDataSize = sizeof ( TInt ); |
|
1090 iSessionDataNotify->NewData( iOverallDataSize ); |
|
1091 } |
|
1092 } |
|
1093 |
|
1094 void CHttpClientFlow::DoReset ( ) |
|
1095 { |
|
1096 iResponseCompleted = EFalse; |
|
1097 iOverallDataSize = 0; |
|
1098 |
|
1099 iRequestUri.Close ( ); |
|
1100 iActionValue.Close ( ); |
|
1101 iRemoteAddress.FillZ ( ); |
|
1102 iBufChain.Free ( ); |
|
1103 |
|
1104 if ( iTransactions->Count() ) |
|
1105 { |
|
1106 CHTTPClientTransaction* ctrans = iTransactions->Get( 0 ); |
|
1107 delete ctrans; |
|
1108 iTransactions->Remove( 0 ); |
|
1109 } |
|
1110 } |