|
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 // |
|
15 |
|
16 #include <ss_glob.h> |
|
17 #include <comms-infras/ss_nodemessages.h> |
|
18 #include <comms-infras/ss_nodemessages_dataclient.h> |
|
19 #include <comms-infras/ss_nodemessages_factory.h> |
|
20 #include <elements/nm_interfaces.h> |
|
21 |
|
22 #include <httpstringconstants.h> |
|
23 #include <httperr.h> |
|
24 #include <http/thttptable.h> |
|
25 #include <http/framework/cheadercodecplugin.h> |
|
26 #include <upnp/tupnptable.h> |
|
27 #include <uriutils.h> |
|
28 |
|
29 #include "app_protintf_msgs.h" |
|
30 #include "httpserver.h" |
|
31 #include "ctransaction.h" |
|
32 #include "httpserverhandler.h" |
|
33 #include "httpevent.h" |
|
34 #include "upnpserverconstants.h" |
|
35 #include "upnplog.h" |
|
36 #include "upnppint.h" |
|
37 #include "upnpmemoryutils.h" |
|
38 |
|
39 __FLOG_STMT(_LIT8(KComponent,"Flow");) |
|
40 |
|
41 using namespace Messages; |
|
42 using namespace ESock; |
|
43 |
|
44 CServiceInfo* CServiceInfo::NewL ( const TDesC8& aUri, MHttpEventObserver& aObserver ) |
|
45 { |
|
46 CServiceInfo* self = new (ELeave) CServiceInfo ( aObserver ); |
|
47 CleanupStack::PushL ( self ); |
|
48 self->ConstructL ( aUri ); |
|
49 CleanupStack::Pop (); // self |
|
50 return self; |
|
51 } |
|
52 |
|
53 TBool CServiceInfo::Match ( const TDesC8& aUri ) |
|
54 { |
|
55 return ( iUri.CompareF ( aUri ) == 0 ); |
|
56 } |
|
57 |
|
58 TBool CServiceInfo::Match ( const TUriC8& aUri, const TDesC8& aHost ) const |
|
59 { |
|
60 // Check host matches |
|
61 if ( aHost.Length () != 0 ) |
|
62 { |
|
63 // Search if aHost has the port also. |
|
64 TInt pos = aHost.Find(_L8(":")); |
|
65 if((pos != KErrNotFound) && (UriUtils::HostType(aHost.Left(pos)) == UriUtils::EIPv4Host)) |
|
66 { |
|
67 // Port number is present in aHost |
|
68 if(iParsedUri.Extract(EUriHost).Compare(aHost.Left(pos)) == 0) |
|
69 { |
|
70 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriHost Matched"))); |
|
71 |
|
72 // Check if the port in aHost matches with the port in iParsedUri |
|
73 if(iParsedUri.Extract(EUriPort).Compare(aHost.Right(aHost.Length()-(pos+1))) !=0 ) |
|
74 { |
|
75 // Port numbers did not match |
|
76 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriPort Not Matched"))); |
|
77 return EFalse; |
|
78 } |
|
79 } |
|
80 else |
|
81 { |
|
82 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriHost Not Matched"))); |
|
83 return EFalse; |
|
84 } |
|
85 } |
|
86 |
|
87 else if ( iParsedUri.Extract ( EUriHost ).CompareF ( aHost ) ) |
|
88 { |
|
89 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriHost Not Matched"))); |
|
90 return EFalse; |
|
91 } |
|
92 } |
|
93 else |
|
94 { |
|
95 // Check if its matches in the Uri |
|
96 if ( iParsedUri.Compare ( aUri, EUriHost ) ) |
|
97 { |
|
98 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriHost Not Matched"))); |
|
99 return EFalse; |
|
100 } |
|
101 } |
|
102 // Check path component matches |
|
103 if ( iParsedUri.Compare ( aUri, EUriPath ) ) |
|
104 { |
|
105 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriPath Not Matched"))); |
|
106 return EFalse; |
|
107 } |
|
108 |
|
109 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("UriPath Matched"))); |
|
110 return ETrue; |
|
111 } |
|
112 |
|
113 CServiceInfo::CServiceInfo ( MHttpEventObserver& aObserver ) |
|
114 : iObserver ( aObserver ) |
|
115 { |
|
116 |
|
117 } |
|
118 |
|
119 void CServiceInfo::ConstructL ( const TDesC8& aUri ) |
|
120 { |
|
121 User::LeaveIfError ( iParsedUri.Parse ( aUri ) ); |
|
122 iUri.CreateL ( aUri ); |
|
123 } |
|
124 |
|
125 CServiceInfo::~CServiceInfo () |
|
126 { |
|
127 iUri.Close (); |
|
128 } |
|
129 |
|
130 MHttpEventObserver& CServiceInfo::Observer () const |
|
131 { |
|
132 return iObserver; |
|
133 } |
|
134 |
|
135 // ------------------------------------------------- |
|
136 |
|
137 CServiceInfoArray::CServiceInfoArray () |
|
138 { |
|
139 } |
|
140 |
|
141 CServiceInfoArray::~CServiceInfoArray () |
|
142 { |
|
143 iServiceInfos.ResetAndDestroy (); |
|
144 } |
|
145 |
|
146 void CServiceInfoArray::AddServiceUriL ( const TDesC8& aUri, MHttpEventObserver& aObserver ) |
|
147 { |
|
148 TInt position = FindServiceUri ( aUri ); |
|
149 if( position != KErrNotFound ) |
|
150 { |
|
151 User::Leave ( KErrAlreadyExists ); |
|
152 } |
|
153 |
|
154 CServiceInfo* info = CServiceInfo::NewL ( aUri, aObserver ); |
|
155 CleanupStack::PushL ( info ); |
|
156 iServiceInfos.AppendL ( info ); |
|
157 CleanupStack::Pop (); // info |
|
158 } |
|
159 |
|
160 void CServiceInfoArray::RemoveServiceUri ( const TDesC8& aUri ) |
|
161 { |
|
162 TInt pos = FindServiceUri ( aUri ); |
|
163 if ( pos != KErrNotFound ) |
|
164 { |
|
165 CServiceInfo* info = iServiceInfos [ pos ]; |
|
166 iServiceInfos.Remove ( pos ); |
|
167 delete info; |
|
168 } |
|
169 } |
|
170 |
|
171 TInt CServiceInfoArray::FindServiceUri ( const TDesC8& aUri ) |
|
172 { |
|
173 for ( TInt i = 0; i < iServiceInfos.Count(); ++i ) |
|
174 { |
|
175 if ( iServiceInfos[i]->Match( aUri ) ) |
|
176 return i; |
|
177 } |
|
178 return KErrNotFound; |
|
179 } |
|
180 |
|
181 TInt CServiceInfoArray::MatchServiceUri ( const TUriC8& aUri, const TDesC8& aHost ) |
|
182 { |
|
183 for ( TInt i = 0; i < iServiceInfos.Count(); ++i ) |
|
184 { |
|
185 if ( iServiceInfos[i]->Match( aUri, aHost ) ) |
|
186 return i; |
|
187 } |
|
188 return KErrNotFound; |
|
189 } |
|
190 |
|
191 TInt CServiceInfoArray::CountServiceUri () |
|
192 { |
|
193 return iServiceInfos.Count(); |
|
194 } |
|
195 |
|
196 // ------------------------------------------------------------- |
|
197 |
|
198 void HttpRequestUtils::ValidateL ( const CRequest& aRequest ) |
|
199 { |
|
200 User::LeaveIfError ( ValidateMethod ( aRequest ) ); |
|
201 User::LeaveIfError ( ValidateHost ( aRequest ) ); |
|
202 } |
|
203 |
|
204 TInt HttpRequestUtils::ValidateMethod ( const CRequest& aRequest ) |
|
205 { |
|
206 // We validate the RFC2616 methods that we support. Currrent we support only |
|
207 // GET and POST method. Other methods are validated in the protocol flow. |
|
208 |
|
209 RStringF method = aRequest.Method (); |
|
210 RStringPool strP = aRequest.StringPool(); |
|
211 |
|
212 RStringF connect = strP.StringF(HTTP::ECONNECT, THTTPTable::Table()); |
|
213 RStringF del = strP.StringF(HTTP::EDELETE, THTTPTable::Table()); |
|
214 RStringF head = strP.StringF(HTTP::EHEAD, THTTPTable::Table()); |
|
215 RStringF options = strP.StringF(HTTP::EOPTIONS, THTTPTable::Table()); |
|
216 RStringF put = strP.StringF(HTTP::EPUT, THTTPTable::Table()); |
|
217 RStringF trace = strP.StringF(HTTP::ETRACE, THTTPTable::Table()); |
|
218 |
|
219 if(aRequest.Method() == connect||aRequest.Method() == del||aRequest.Method() == head|| |
|
220 aRequest.Method() == options||aRequest.Method() == put||aRequest.Method() == trace |
|
221 ) |
|
222 { |
|
223 return KErrNotSupported; |
|
224 } |
|
225 else |
|
226 { |
|
227 return KErrNone; |
|
228 } |
|
229 } |
|
230 |
|
231 TInt HttpRequestUtils::ValidateHost ( const CRequest& aRequest ) |
|
232 { |
|
233 if ( !aRequest.IsHTTP10 () ) |
|
234 { |
|
235 // HTTP/1.1 Host header must be present. |
|
236 // Relevant information from RFC2616 Sec 14.23 |
|
237 // 1. A client MUST include a Host header field in all HTTP/1.1 request messages . |
|
238 // 2. If the requested URI does not include an Internet host name for the service being requested, then the Host header |
|
239 // field MUST be given with an empty value. |
|
240 // Also from sec 19.6.1.1 - Servers MUST report a 400 (Bad Request) error if an HTTP/1.1 request does not include a Host |
|
241 // request-header. |
|
242 // For more information refer the above sections in RFC2616 |
|
243 |
|
244 // Note: ( seee above 2 ) - RFC2616 explicitly is not saying what we should do when we are having Host header field with |
|
245 // emtpy value. Only it mandates the Host header field MUST be present if it is a HTTP/1.1 request. So we just check |
|
246 // the presence of Host header field and we will leave rest to URI matching. |
|
247 if ( !HttpRequestUtils::IsHostPresent ( aRequest ) ) |
|
248 { |
|
249 return KErrCorrupt; |
|
250 } |
|
251 } |
|
252 return KErrNone; |
|
253 } |
|
254 |
|
255 TBool HttpRequestUtils::IsHostPresent ( const CRequest& aRequest ) |
|
256 { |
|
257 CRequest& req = const_cast < CRequest& > ( aRequest ); |
|
258 RRequest request = req.Handle (); |
|
259 RHTTPHeaders headers = request.GetHeaderCollection (); |
|
260 RStringF hostStr = aRequest.StringPool ().StringF ( HTTP::EHost, THTTPTable::Table() ); |
|
261 THTTPHdrVal hostValue; |
|
262 return headers.GetField(hostStr, 0, hostValue) == KErrNone; |
|
263 } |
|
264 |
|
265 const TDesC8& HttpRequestUtils::HostStr ( const CRequest& aRequest ) |
|
266 { |
|
267 CRequest& req = const_cast < CRequest& > ( aRequest ); |
|
268 RStringF hostStr = aRequest.StringPool ().StringF ( HTTP::EHost, THTTPTable::Table() ); |
|
269 RHTTPHeaders headers = req.Handle ().GetHeaderCollection (); |
|
270 THTTPHdrVal hostValue; |
|
271 if ( headers.GetField(hostStr, 0, hostValue) != KErrNotFound ) |
|
272 { |
|
273 return hostValue.StrF ().DesC (); |
|
274 } |
|
275 return KNullDesC8 (); |
|
276 } |
|
277 |
|
278 TBool HttpRequestUtils::IsConnectionRequired ( const CRequest& aRequest ) |
|
279 { |
|
280 TBool bConnRequired = EFalse; |
|
281 CRequest& req = const_cast < CRequest& > ( aRequest ); |
|
282 RRequest request = req.Handle (); |
|
283 RHTTPHeaders headers = request.GetHeaderCollection (); |
|
284 RStringF name = aRequest.StringPool ().StringF ( HTTP::EConnection, THTTPTable::Table() ); |
|
285 THTTPHdrVal value; |
|
286 |
|
287 if ( request.IsHTTP10 () ) // HTTP 1.0 request, check for keep alive header value. |
|
288 { |
|
289 // Check for Connection: Keep Alive header |
|
290 if ( headers.GetField ( name, 0, value ) == KErrNone && |
|
291 value.Type ( ) == THTTPHdrVal::KStrFVal && |
|
292 value.StrF ( ).Index ( THTTPTable::Table() ) == HTTP::EKeepAlive ) |
|
293 { |
|
294 bConnRequired = ETrue; |
|
295 } |
|
296 } |
|
297 else // HTTP 1.1 |
|
298 { |
|
299 // Check for Connection: Keep Alive header |
|
300 if ( headers.GetField ( name, 0, value ) == KErrNone && |
|
301 value.Type ( ) == THTTPHdrVal::KStrFVal && |
|
302 value.StrF ( ).Index ( THTTPTable::Table() ) == HTTP::EClose ) |
|
303 { |
|
304 bConnRequired = EFalse; |
|
305 } |
|
306 else |
|
307 { |
|
308 bConnRequired = ETrue; |
|
309 } |
|
310 } |
|
311 return bConnRequired; |
|
312 } |
|
313 |
|
314 // -------------------------------------------------------------- |
|
315 |
|
316 CHttpServer* CHttpServer::NewL (ESock::CProtocolIntfBase* aProtIntf) |
|
317 { |
|
318 CHttpServer* self = new (ELeave)CHttpServer(aProtIntf); |
|
319 CleanupStack::PushL ( self ); |
|
320 self->ConstructL (); |
|
321 CleanupStack::Pop (); |
|
322 return self; |
|
323 } |
|
324 |
|
325 CHttpServer::CHttpServer (ESock::CProtocolIntfBase* aProtIntf) : |
|
326 iStarted ( EFalse ), iIsLeaving ( EFalse ), iProtIntf ( aProtIntf ) |
|
327 { |
|
328 LOG_NODE_CREATE ( KESockFlowTag, CHttpServer ); |
|
329 } |
|
330 |
|
331 CHttpServer::~CHttpServer () |
|
332 { |
|
333 delete iServiceInfos; |
|
334 delete iParser; |
|
335 delete iComposer; |
|
336 delete iTransaction; |
|
337 if ( !iMemChunk.IsEmpty() ) |
|
338 iMemChunk.Free (); |
|
339 iServerHandlerArray.ResetAndDestroy (); |
|
340 iServiceControlProviderInfos.Reset (); |
|
341 iServiceControlProviderInfos.Close (); |
|
342 //delete iCodec; |
|
343 iStringPool.Close(); |
|
344 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("Destroyed CHttpServer"))); |
|
345 LOG_NODE_DESTROY(KESockFlowTag, CHttpServer); |
|
346 } |
|
347 |
|
348 void CHttpServer::ConstructL () |
|
349 { |
|
350 iStringPool.OpenL(TUPnPTable::Table()); |
|
351 iStringPool.OpenL(THTTPTable::Table()); |
|
352 iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool ); |
|
353 |
|
354 iParser = CUpnpRequestParser::NewL ( *this ); |
|
355 iComposer = CUpnpResponseComposer::NewL ( *this ); |
|
356 iTransaction = CTransaction::NewL ( *iCodec, iStringPool ); |
|
357 iServiceInfos = new ( ELeave ) CServiceInfoArray; |
|
358 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("Created CHttpServer"))); |
|
359 } |
|
360 |
|
361 void CHttpServer::AddServiceUriL ( const TDesC8& aUri, MHttpEventObserver& aObserver, TNodeCtxId aServiceId, TNodeCtxId aControlProviderId ) |
|
362 { |
|
363 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::AddServiceUriL"))); |
|
364 iServiceInfos->AddServiceUriL ( aUri, aObserver ); |
|
365 |
|
366 if ( iAppProtIntfId == TNodeId::NullId () && iServiceControlProviderInfos.Count () == 0 ) |
|
367 { |
|
368 CreateListener (); |
|
369 } |
|
370 |
|
371 if ( !iStarted ) |
|
372 { |
|
373 TServiceControlProviderInfo newInfo ( aServiceId, aControlProviderId ); |
|
374 iServiceControlProviderInfos.Append ( newInfo ); |
|
375 } |
|
376 else |
|
377 { |
|
378 RClientInterface::OpenPostMessageClose ( aServiceId, aControlProviderId, ESock::TCFDataClient::TStarted ().CRef () ); |
|
379 } |
|
380 |
|
381 } |
|
382 |
|
383 TBool CHttpServer::RemoveServiceUri ( const TDesC8& aUri, TNodeCtxId aServiceId, TNodeCtxId aControlProviderId ) |
|
384 { |
|
385 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::RemoveServiceUri"))); |
|
386 iServiceInfos->RemoveServiceUri ( aUri ); |
|
387 |
|
388 if ( iServiceInfos->CountServiceUri () == 0 ) // last service is stopped, so stop listener |
|
389 { |
|
390 iLastServiceControlProviderInfo.iServiceId = aServiceId; |
|
391 iLastServiceControlProviderInfo.iControlProviderId = aControlProviderId; |
|
392 |
|
393 iIsLeaving = ETrue; |
|
394 StopServer (); |
|
395 return ETrue; |
|
396 } |
|
397 |
|
398 if ( TNodeId::NullId () != aControlProviderId ) |
|
399 { |
|
400 RClientInterface::OpenPostMessageClose ( aServiceId, aControlProviderId, TCFDataClient::TStopped ( 0 ).CRef () ); |
|
401 } |
|
402 return EFalse; |
|
403 } |
|
404 |
|
405 TBool CHttpServer::MatchRequestUri () const |
|
406 { |
|
407 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::MatchRequestUri"))); |
|
408 CRequest* request = iTransaction->Request (); |
|
409 return iServiceInfos->MatchServiceUri ( request->Handle ().URI (), HttpRequestUtils::HostStr ( *(iTransaction->Request ()) ) ) != KErrNotFound ? ETrue : EFalse; |
|
410 } |
|
411 |
|
412 void CHttpServer::CreateListener () |
|
413 { |
|
414 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::CreateListener"))); |
|
415 const TInt KAppProtIntfFactoryUid = 0x2000D05B; // Put in common place |
|
416 // const TInt KGenericContainerIndex = 1; |
|
417 const TInt KListenPort = 80; // Maybe we should make it as configurable and multiple ports |
|
418 TAppProtIntfQuery query ( KProtocolInetTcp, KListenPort ); |
|
419 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::CreateListener - Posting message TCFMessage::TFindOrCreateFactoryObject"))); |
|
420 |
|
421 TCFFactory::TFindOrCreatePeer foMsg ( TCFPlayerRole::EDataPlane, TUid::Uid( KAppProtIntfFactoryUid ), &query ); |
|
422 // foMsg.PostTo ( SockManGlobals::Get()->GetPlaneFC ( EDataPlane, KGenericContainerIndex ) ); |
|
423 TNodeId containerId = static_cast<CUPnPProtocolIntfBase*>(iProtIntf)->GetAppProtIntfContainerId(); |
|
424 if(containerId != TNodeId::NullId ( )) |
|
425 { |
|
426 RClientInterface::OpenPostMessageClose ( NodeId (), containerId, foMsg ); |
|
427 } |
|
428 } |
|
429 |
|
430 |
|
431 |
|
432 void CHttpServer::ReceivedL ( const TRuntimeCtxId& /*aSender*/, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage ) |
|
433 { |
|
434 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL"))); |
|
435 |
|
436 if ( aMessage.MessageId ().Realm () == TCFFactory::ERealmId ) |
|
437 { |
|
438 if ( aMessage.MessageId().MessageId() == TCFFactory::TPeerFoundOrCreated::EId ) |
|
439 { |
|
440 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TCFMessage::TFOCreated"))); |
|
441 const TCFFactory::TPeerFoundOrCreated & msg = message_cast < const TCFFactory::TPeerFoundOrCreated > ( aMessage ); |
|
442 iAppProtIntfId = msg.iNodeId; |
|
443 RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TJoin ().CRef () ); |
|
444 } |
|
445 } |
|
446 else |
|
447 { |
|
448 switch ( aMessage.MessageId().MessageId() ) |
|
449 { |
|
450 case TAppProtIntfMessage::TJoinComplete::EId: |
|
451 { |
|
452 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TAppProtIntfMessage::TJoinComplete"))); |
|
453 |
|
454 // We joined. Now we started listening for incomming connections |
|
455 iStarted = ETrue; |
|
456 |
|
457 for ( TInt i = 0; i < iServiceControlProviderInfos.Count (); i++ ) |
|
458 { |
|
459 RClientInterface::OpenPostMessageClose ( iServiceControlProviderInfos[i].iServiceId, iServiceControlProviderInfos[i].iControlProviderId, TCFDataClient::TStarted ().CRef () ); |
|
460 } |
|
461 iServiceControlProviderInfos.Reset (); |
|
462 } |
|
463 break; |
|
464 |
|
465 case TAppProtIntfMessage::TNewConnection::EId: |
|
466 { |
|
467 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TAppProtIntfMessage::TNewConnection"))); |
|
468 |
|
469 TAppProtIntfMessage::TNewConnection& currentMsg = message_cast < TAppProtIntfMessage::TNewConnection > ( aMessage ); |
|
470 |
|
471 if ( !iIsLeaving ) |
|
472 { |
|
473 RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( iProtIntf )->GetMemoryChunkManager()); |
|
474 if ( iMemChunk.IsEmpty() ) |
|
475 { |
|
476 TUPnPMemoryUtils::CreateMemChunk(iMemChunk, currentMsg.iData, allocator); |
|
477 RMemChunk memChunk = iMemChunk; |
|
478 iParser->ParseRequest ( memChunk, iTransaction->Request() ); |
|
479 } |
|
480 else |
|
481 { |
|
482 //In case of More data parse only new data and then append to iMemChunk. |
|
483 RMemChunk mChunk; |
|
484 TUPnPMemoryUtils::CreateMemChunk(mChunk, currentMsg.iData, allocator); |
|
485 RMemChunk memChunk = mChunk; |
|
486 iParser->ParseRequest ( memChunk, iTransaction->Request() ); |
|
487 iMemChunk.Append(mChunk); |
|
488 } |
|
489 } |
|
490 } |
|
491 break; |
|
492 |
|
493 case TAppProtIntfMessage::TTransferConnection::EId: |
|
494 { |
|
495 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TAppProtIntfMessage::TTransferConnection"))); |
|
496 // Now we are going to accept the connection. Create a new server handler and reset the parser |
|
497 TAppProtIntfMessage::TTransferConnection& msg = message_cast < TAppProtIntfMessage::TTransferConnection > ( aMessage ); |
|
498 |
|
499 TransferConnectionL ( msg.iSocket, msg.iData ); |
|
500 } |
|
501 break; |
|
502 |
|
503 case TAppProtIntfMessage::TLeaveComplete::EId: |
|
504 { |
|
505 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TAppProtIntfMessage::TLeaveComplete"))); |
|
506 |
|
507 // post dataclient stopped to controlprovider |
|
508 if ( TNodeId::NullId () != iLastServiceControlProviderInfo.iControlProviderId ) |
|
509 { |
|
510 RClientInterface::OpenPostMessageClose ( iLastServiceControlProviderInfo.iServiceId, iLastServiceControlProviderInfo.iControlProviderId, TCFDataClient::TStopped ( 0 ).CRef () ); |
|
511 } |
|
512 |
|
513 // post destroy to service provider |
|
514 RClientInterface::OpenPostMessageClose ( NodeId (), iAppProtIntfId, TAppProtIntfMessage::TDestroy ().CRef () ); |
|
515 |
|
516 // make self destruction |
|
517 delete this; |
|
518 } |
|
519 break; |
|
520 |
|
521 case TAppProtIntfMessage::TError::EId: |
|
522 { |
|
523 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::ReceivedL - TAppProtIntfMessage::TError"))); |
|
524 //Note! Nothing to do if already leaving state, |
|
525 // else need to send error to control clients and do listener cleanup |
|
526 } |
|
527 break; |
|
528 |
|
529 default: |
|
530 break; |
|
531 } |
|
532 } |
|
533 } |
|
534 |
|
535 void CHttpServer::StopServer () |
|
536 { |
|
537 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::StopServer - Posting message TAppProtIntfMessage::TLeave"))); |
|
538 RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TClientLeavingRequest ().CRef () ); |
|
539 } |
|
540 |
|
541 void CHttpServer::GotHeaders() |
|
542 { |
|
543 TRAPD(err, HttpRequestUtils::ValidateL(*(iTransaction->Request()))); |
|
544 if(err == KErrCorrupt) |
|
545 { |
|
546 // Generate an error response. 400 Bad Request |
|
547 CHttpServerHandler::CreateResponse ( *(iTransaction->Response ()), HTTPStatus::EBadRequest ); |
|
548 iComposer->ComposeResponse ( iTransaction->Response () ); |
|
549 } |
|
550 |
|
551 // If we are accepting the connection application protocol interface will |
|
552 // send a TTransferConnection msg. In other case we will send a 404 Not Found response |
|
553 else if ( MatchRequestUri () ) |
|
554 { |
|
555 RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TAcceptConnection ().CRef () ); |
|
556 } |
|
557 else |
|
558 { |
|
559 // Generate an error response. 404 Not Found |
|
560 CHttpServerHandler::CreateResponse ( *(iTransaction->Response ()), HTTPStatus::ENotFound ); |
|
561 iComposer->ComposeResponse ( iTransaction->Response () ); |
|
562 } |
|
563 // We can reset the parser now as we completed the URI matching. |
|
564 // Reset the parser as we don't need to parse anymore |
|
565 iParser->ResetParser (); |
|
566 } |
|
567 |
|
568 void CHttpServer::DataParsed () |
|
569 { |
|
570 RClientInterface::OpenPostMessageClose ( NodeId (), iAppProtIntfId, TAppProtIntfMessage::TMoreData ().CRef () ); |
|
571 } |
|
572 |
|
573 void CHttpServer::ParserError ( TInt /*aError*/ ) |
|
574 { |
|
575 // Reset the parser as we don't need to parse anymore |
|
576 iParser->ResetParser (); |
|
577 // Generate an error response. 400 Bad request |
|
578 CHttpServerHandler::CreateResponse ( *(iTransaction->Response ()), HTTPStatus::EBadRequest ); |
|
579 iComposer->ComposeResponse ( iTransaction->Response () ); |
|
580 } |
|
581 |
|
582 void CHttpServer::MessageDataReadyL ( RBuf8& aData ) |
|
583 { |
|
584 RMBufChain data; //Need to Check |
|
585 data.CreateL(aData); |
|
586 RejectConnection ( data ); |
|
587 iComposer->ResponseDataSent (); |
|
588 iComposer->ResetComposer (); // composer's DataState is left in WaitingForRelease, so Reset it |
|
589 } |
|
590 |
|
591 void CHttpServer::ComposerError ( TInt /*aError*/ ) |
|
592 { |
|
593 RMBufChain data; |
|
594 RejectConnection ( data ); |
|
595 iComposer->ResetComposer (); |
|
596 } |
|
597 |
|
598 void CHttpServer::RejectConnection ( RMBufChain& aData ) |
|
599 { |
|
600 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::RejectConnection"))); |
|
601 |
|
602 // Sending an eror response. |
|
603 TAppProtIntfMessage::TRejectConnection msg ( aData ); |
|
604 RClientInterface::OpenPostMessageClose ( NodeId (), iAppProtIntfId, msg ); |
|
605 |
|
606 // Reset our current transaction |
|
607 iTransaction->Reset (); |
|
608 } |
|
609 |
|
610 |
|
611 void CHttpServer::TransferConnectionL ( RInternalSocket& aSocket, RMBufChain& aData ) |
|
612 { |
|
613 LOG(ESockLogExternal::Printf(KSubsysHttpServer, KComponent, _L8("CHttpServer::TransferConnectionL"))); |
|
614 |
|
615 if ( iIsLeaving ) |
|
616 { |
|
617 aSocket.Close (); |
|
618 } |
|
619 else |
|
620 { |
|
621 CChunkManager* chunkMgr = static_cast<CUPnPProtocolIntfBase *>( iProtIntf )->GetMemoryChunkManager(); |
|
622 CHttpServerHandler* serverHandler = CHttpServerHandler::NewL ( aSocket, iMemChunk, *iServiceInfos, iServerHandlerArray, *iCodec, iStringPool, chunkMgr ); |
|
623 CleanupStack::PushL ( serverHandler ); |
|
624 iServerHandlerArray.AppendL ( serverHandler ); |
|
625 CleanupStack::Pop (); // serverHandler |
|
626 |
|
627 iTransaction->Reset (); |
|
628 } |
|
629 aData.Free (); |
|
630 |
|
631 } |