|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Push transport server |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 // INCLUDE FILES |
|
24 // System |
|
25 #include <es_sock.h> |
|
26 #include <in_sock.h> |
|
27 |
|
28 // upnp stack api's |
|
29 #include <upnphttpserversession.h> |
|
30 #include <upnphttpserverruntime.h> |
|
31 #include <upnphttpserverobserver.h> |
|
32 #include <upnphttpservertransaction.h> |
|
33 #include <upnphttpservertransactioncreator.h> |
|
34 #include <upnphttpmessage.h> |
|
35 |
|
36 // dlnasrv / mediaserver api |
|
37 #include <upnpitem.h> |
|
38 #include "upnpdlnafilter.h" |
|
39 |
|
40 // dlnasrv / internal api's |
|
41 #include "upnpconstantdefs.h" // for upnp-specific stuff |
|
42 #include "upnpitemutility.h" // for GetResElements |
|
43 |
|
44 |
|
45 _LIT( KComponentLogfile, "upnppushserver.txt"); |
|
46 #include "upnplog.h" |
|
47 #include "upnppushserver.h" |
|
48 |
|
49 // CONSTANTS |
|
50 const TUint KMaxItemResourcesCount = 8; |
|
51 const TUint KMaxBufferSize = 64; |
|
52 const TUint KMaxUriLength = 256; |
|
53 const TInt KSlash = 47; // '/' |
|
54 const TInt KDot = 46; // '.' |
|
55 |
|
56 _LIT8( KHttp, "http://" ); |
|
57 _LIT8( KSeparatorcolon, ":" ); |
|
58 _LIT8( KSeparatorSlash, "/" ); |
|
59 // GLOBALS |
|
60 |
|
61 |
|
62 // -------------------------------------------------------------------------- |
|
63 // CUpnpPushServer::ShareL |
|
64 // |
|
65 //--------------------------------------------------------------------------- |
|
66 EXPORT_C void CUpnpPushServer::ShareL( |
|
67 TUint aHash, |
|
68 CUpnpItem& aItem ) |
|
69 { |
|
70 __LOG( "PushServer::ShareL()" ); |
|
71 RUPnPElementsArray resources; |
|
72 CleanupClosePushL( resources ); |
|
73 UPnPItemUtility::GetResElements( aItem, resources ); |
|
74 if ( resources.Count() == 0 ) |
|
75 { |
|
76 __LOG( "PushServer::ShareL() - no resources" ); |
|
77 User::Leave(KErrNotFound); |
|
78 } |
|
79 |
|
80 CUpnpPushServer* singleton = static_cast<CUpnpPushServer*>( Dll::Tls() ); |
|
81 if ( !singleton ) |
|
82 { |
|
83 // singleton must be created first |
|
84 __LOG( "PushServer::ShareL: creating singleton" ); |
|
85 singleton = new (ELeave) CUpnpPushServer(); |
|
86 CleanupStack::PushL( singleton ); |
|
87 singleton->ConstructL(); |
|
88 User::LeaveIfError( Dll::SetTls( singleton ) ); |
|
89 CleanupStack::Pop( singleton ); |
|
90 } |
|
91 |
|
92 CUpnpElement* elem = |
|
93 (CUpnpElement*)(UPnPItemUtility::FindElementByName( |
|
94 aItem, KElementAlbumArtUri() )); |
|
95 if( elem ) |
|
96 { |
|
97 singleton->ShareResourceL( aHash, *elem ); |
|
98 aHash += 1; |
|
99 } |
|
100 |
|
101 for( TUint i(0); i<resources.Count(); ++i ) |
|
102 { |
|
103 singleton->ShareResourceL( aHash+i, *resources[i] ); |
|
104 } |
|
105 |
|
106 CleanupStack::PopAndDestroy( &resources ); |
|
107 } |
|
108 |
|
109 // -------------------------------------------------------------------------- |
|
110 // CUpnpPushServer::Unshare |
|
111 // |
|
112 //--------------------------------------------------------------------------- |
|
113 EXPORT_C void CUpnpPushServer::UnshareL( |
|
114 TUint aHash ) |
|
115 { |
|
116 CUpnpPushServer* singleton = static_cast<CUpnpPushServer*>( Dll::Tls() ); |
|
117 if ( singleton == 0 ) return; // singleton is empty, nothing to share. |
|
118 |
|
119 // assume item would have max. 8 resources, call unshare for those |
|
120 for( TUint i=0; i<KMaxItemResourcesCount; ++i ) |
|
121 { |
|
122 singleton->UnshareResource( aHash+i ); |
|
123 } |
|
124 |
|
125 if ( singleton->EntryCount() == 0 ) |
|
126 { |
|
127 __LOG( "PushServer::Unshare: destroying singleton" ); |
|
128 Dll::FreeTls(); |
|
129 delete singleton; |
|
130 } |
|
131 } |
|
132 |
|
133 // -------------------------------------------------------------------------- |
|
134 // CUpnpPushServer::UnshareAll |
|
135 // |
|
136 //--------------------------------------------------------------------------- |
|
137 EXPORT_C void CUpnpPushServer::UnshareAllL() |
|
138 { |
|
139 CUpnpPushServer* singleton = static_cast<CUpnpPushServer*>( Dll::Tls() ); |
|
140 if ( singleton != 0 ) |
|
141 { |
|
142 __LOG( "PushServer::UnshareAll: destroying singleton" ); |
|
143 Dll::FreeTls(); |
|
144 delete singleton; |
|
145 } |
|
146 } |
|
147 |
|
148 // -------------------------------------------------------------------------- |
|
149 // CUpnpPushServer::IsRunning |
|
150 // |
|
151 //--------------------------------------------------------------------------- |
|
152 EXPORT_C TBool CUpnpPushServer::IsRunning() |
|
153 { |
|
154 CUpnpPushServer* singleton = static_cast<CUpnpPushServer*>( Dll::Tls() ); |
|
155 return (singleton ? ETrue : EFalse); |
|
156 } |
|
157 |
|
158 // -------------------------------------------------------------------------- |
|
159 // CUpnpPushServer::ShareResourceL |
|
160 // |
|
161 //--------------------------------------------------------------------------- |
|
162 void CUpnpPushServer::ShareResourceL( |
|
163 TUint aHash, |
|
164 CUpnpElement& aResource ) |
|
165 { |
|
166 // catch protocol info if one exists |
|
167 const CUpnpAttribute* piAttr = UPnPItemUtility::FindAttributeByName( |
|
168 aResource, KAttributeProtocolInfo() ); |
|
169 |
|
170 // create URI |
|
171 TBuf8<KMaxBufferSize> uri; |
|
172 TParse parse; |
|
173 TInt result = parse.Set( aResource.FilePath(), NULL, NULL ); |
|
174 User::LeaveIfError(result); |
|
175 HashToUri( aHash, parse.Ext(), uri ); |
|
176 aResource.SetValueL( uri ); |
|
177 |
|
178 // add to share |
|
179 __LOG2( "PushServer::ShareResourceL %d = %S", |
|
180 aHash, &aResource.FilePath() ); |
|
181 __LOG8( uri ); |
|
182 TUpnpPushEntry entry(aHash, aResource.FilePath(), |
|
183 ( piAttr ? piAttr->Value() : KNullDesC8 ) ); |
|
184 iEntries.InsertL( aHash, entry ); |
|
185 } |
|
186 |
|
187 |
|
188 // -------------------------------------------------------------------------- |
|
189 // CUpnpPushServer::UnshareResource |
|
190 // |
|
191 //--------------------------------------------------------------------------- |
|
192 void CUpnpPushServer::UnshareResource( TUint aHash ) |
|
193 { |
|
194 iEntries.Remove( aHash ); |
|
195 } |
|
196 |
|
197 // -------------------------------------------------------------------------- |
|
198 // CUpnpPushServer::EntryCount |
|
199 // |
|
200 //--------------------------------------------------------------------------- |
|
201 TInt CUpnpPushServer::EntryCount() |
|
202 { |
|
203 return iEntries.Count(); |
|
204 } |
|
205 |
|
206 // -------------------------------------------------------------------------- |
|
207 // CUpnpPushServer::HashToUri |
|
208 // |
|
209 //--------------------------------------------------------------------------- |
|
210 void CUpnpPushServer::HashToUri( TUint aHash, const TDesC& aFileExt, |
|
211 TDes8& aUriBuf ) |
|
212 { |
|
213 TInetAddr addr; |
|
214 iHttpServer->GetAddress( addr ); |
|
215 TBuf<KMaxBufferSize> ip; |
|
216 addr.Output( ip ); |
|
217 |
|
218 aUriBuf.Append( KHttp() ); // http:// |
|
219 aUriBuf.Append( ip ); // http://n.n.n.n |
|
220 aUriBuf.Append( KSeparatorcolon() ); // http://n.n.n.n: |
|
221 aUriBuf.AppendNum( addr.Port() ); // http://n.n.n.n:pppp |
|
222 aUriBuf.Append( KSeparatorSlash() ); // http://n.n.n.n:pppp/ |
|
223 aUriBuf.AppendNum( aHash ); // http://n.n.n.n:pppp/hash |
|
224 aUriBuf.Append( aFileExt ); // http://n.n.n.n:pppp/hash.ext |
|
225 } |
|
226 |
|
227 // -------------------------------------------------------------------------- |
|
228 // CUpnpPushServer::HashFromUri |
|
229 // |
|
230 //--------------------------------------------------------------------------- |
|
231 TUint CUpnpPushServer::HashFromUri( const TDesC8& aUri ) |
|
232 { |
|
233 TBuf16<KMaxUriLength> uri16; |
|
234 uri16.Copy( aUri ); |
|
235 return HashFromUri( uri16 ); |
|
236 } |
|
237 |
|
238 // -------------------------------------------------------------------------- |
|
239 // CUpnpPushServer::HashFromUri |
|
240 // |
|
241 //--------------------------------------------------------------------------- |
|
242 TUint CUpnpPushServer::HashFromUri( const TDesC16& aUri ) |
|
243 { |
|
244 TUint hash = 0; |
|
245 TChar slash( KSlash ); |
|
246 TChar dot( KDot ); |
|
247 // extract the hash part |
|
248 TInt begin = aUri.LocateReverse( slash ); |
|
249 if ( begin<0 ) |
|
250 { |
|
251 begin = -1; |
|
252 } |
|
253 TInt end = aUri.LocateReverse( dot ); |
|
254 if ( end<0 ) |
|
255 { |
|
256 end = aUri.Length(); |
|
257 } |
|
258 TPtrC16 hashPart = aUri.Mid( |
|
259 begin+1, end-begin-1 ); |
|
260 // convert to a number |
|
261 TLex16 hashLex( hashPart ); |
|
262 if ( hashLex.Val( hash, EDecimal ) != KErrNone ) |
|
263 { |
|
264 // hashcode was not found |
|
265 hash = 0; |
|
266 } |
|
267 __LOG2( "PushServer: HashFromUri: %S -> %d", &aUri, hash ); |
|
268 return hash; |
|
269 } |
|
270 |
|
271 |
|
272 // -------------------------------------------------------------------------- |
|
273 // CUpnpPushServer::CUpnpPushServer |
|
274 // |
|
275 //--------------------------------------------------------------------------- |
|
276 CUpnpPushServer::CUpnpPushServer() |
|
277 :iEntries() |
|
278 { |
|
279 __LOG( "PushServer::CUpnpPushServer()" ); |
|
280 |
|
281 } |
|
282 |
|
283 // -------------------------------------------------------------------------- |
|
284 // CUpnpPushServer::ConstructL |
|
285 // |
|
286 //--------------------------------------------------------------------------- |
|
287 void CUpnpPushServer::ConstructL() |
|
288 { |
|
289 __LOG( "PushServer::ConstructL()" ); |
|
290 |
|
291 iHttpServer = CUpnpHttpServerSession::NewL( 0, *this ); |
|
292 |
|
293 TRAPD( err, iHttpServer->StartL( KPushServerPort ) ); |
|
294 if( err ) |
|
295 { |
|
296 //fixed port already in use -> start with random port |
|
297 iHttpServer->StartL(); |
|
298 } |
|
299 |
|
300 iHttpServer->DefaultRuntime().SetCreator( *this ); |
|
301 iFilter = CUpnpDlnaFilter::NewL( this, NULL ); |
|
302 |
|
303 __LOG( "PushServer::ConstructL() - end" ); |
|
304 } |
|
305 |
|
306 // -------------------------------------------------------------------------- |
|
307 // CUpnpPushServer::CUpnpPushServer |
|
308 // |
|
309 //--------------------------------------------------------------------------- |
|
310 CUpnpPushServer::~CUpnpPushServer() |
|
311 { |
|
312 __LOG( "PushServer::~CUpnpPushServer()" ); |
|
313 iEntries.Close(); |
|
314 if(NULL != iHttpServer) |
|
315 { |
|
316 iHttpServer->Stop(); |
|
317 } |
|
318 delete iHttpServer; |
|
319 delete iFilter; |
|
320 } |
|
321 |
|
322 // -------------------------------------------------------------------------- |
|
323 // CUpnpPushServer::NewTransactionL |
|
324 // |
|
325 //--------------------------------------------------------------------------- |
|
326 void CUpnpPushServer::NewTransactionL( |
|
327 const TDesC8& aMethod, |
|
328 const TDesC8& aUri, |
|
329 const TInetAddr& aSender, |
|
330 CUpnpHttpServerTransaction*& aTrans ) |
|
331 { |
|
332 TBuf<KMaxBufferSize> ip; |
|
333 aSender.Output(ip); |
|
334 if ( aMethod == KHttpGet() || aMethod == KHttpHead() ) |
|
335 { |
|
336 __LOG2( "PushServer: HTTP %S from=%S, launching transaction", &aMethod, |
|
337 &ip ); |
|
338 iFilter->NewTransactionL( aMethod, aUri, aSender, aTrans ); |
|
339 } |
|
340 else |
|
341 { |
|
342 // this method not supported |
|
343 __LOG2( "PushServer: unsupported request: %S from=%S", &aMethod, &ip ); |
|
344 User::Leave( KErrNotSupported ); |
|
345 } |
|
346 } |
|
347 |
|
348 // -------------------------------------------------------------------------- |
|
349 // CUpnpPushServer::HttpEventLD |
|
350 // |
|
351 //--------------------------------------------------------------------------- |
|
352 void CUpnpPushServer::HttpEventLD( CUpnpHttpMessage* aMessage ) |
|
353 { |
|
354 __LOG1( "QuickShare:HttpEventLD() type=%d", aMessage->Type() ); |
|
355 |
|
356 delete aMessage; |
|
357 } |
|
358 |
|
359 // -------------------------------------------------------------------------- |
|
360 // CUpnpPushServer::CheckImportUriL |
|
361 // |
|
362 //--------------------------------------------------------------------------- |
|
363 TInt CUpnpPushServer::CheckImportUriL( const TDesC8& /*aImportUri*/ ) |
|
364 { |
|
365 // should never be here |
|
366 __PANIC( __FILE__, __LINE__ ); |
|
367 return 0; |
|
368 } |
|
369 |
|
370 // -------------------------------------------------------------------------- |
|
371 // CUpnpPushServer::GetTitleForUriL |
|
372 // |
|
373 //--------------------------------------------------------------------------- |
|
374 void CUpnpPushServer::GetTitleForUriL( TInt /*aObjectId*/, TPtr& /*aValue*/ ) |
|
375 { |
|
376 // should never be here |
|
377 __PANIC( __FILE__, __LINE__ ); |
|
378 } |
|
379 |
|
380 // -------------------------------------------------------------------------- |
|
381 // CUpnpPushServer::GetProtocolInfoL |
|
382 // |
|
383 //--------------------------------------------------------------------------- |
|
384 TInt CUpnpPushServer::GetProtocolInfoL( const TDesC8& aContentUri, |
|
385 CUpnpDlnaProtocolInfo*& aProtocolInfo ) |
|
386 { |
|
387 aProtocolInfo = 0; |
|
388 TInt result = KErrNotFound; |
|
389 TUpnpPushEntry* entry = iEntries.Find( HashFromUri( aContentUri ) ); |
|
390 if ( entry ) |
|
391 { |
|
392 aProtocolInfo = CUpnpDlnaProtocolInfo::NewL( entry->ProtocolInfo() ); |
|
393 result = KErrNone; |
|
394 } |
|
395 return result; |
|
396 } |
|
397 |
|
398 // -------------------------------------------------------------------------- |
|
399 // CUpnpPushServer::FindSharedFolderL |
|
400 // |
|
401 //--------------------------------------------------------------------------- |
|
402 TInt CUpnpPushServer::FindSharedFolderL( const TDesC& /*aUrlPath*/, |
|
403 const TDesC& aFileName, HBufC*& aFolderPath ) |
|
404 { |
|
405 aFolderPath = 0; |
|
406 TInt result = KErrNotFound; |
|
407 TUpnpPushEntry* entry = iEntries.Find( HashFromUri( aFileName ) ); |
|
408 if ( entry ) |
|
409 { |
|
410 aFolderPath = entry->Path().AllocL(); |
|
411 result = KErrNone; |
|
412 } |
|
413 return result; |
|
414 } |
|
415 |
|
416 // -------------------------------------------------------------------------- |
|
417 // CUpnpPushServer::GetProtocolInfoByImportUriL |
|
418 // |
|
419 //--------------------------------------------------------------------------- |
|
420 CUpnpDlnaProtocolInfo* CUpnpPushServer::GetProtocolInfoByImportUriL( |
|
421 const TDesC8& /*aImportUri */) |
|
422 { |
|
423 // should never be here |
|
424 __PANIC( __FILE__, __LINE__ ); |
|
425 return 0; |
|
426 } |
|
427 |