--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/controlpointbase/src/upnpcpbdescriptionagent.cpp Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,631 @@
+/** @file
+* Copyright (c) 2007-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Declares ControlPoint Discovery class.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32base.h>
+
+#include <upnpdevice.h>
+#include <upnpdevicedescription.h>
+
+#include <upnphttpmessagefactory.h>
+
+#include "upnpcontrolpoint.h"
+#include "upnpcpbdescriptionagent.h"
+#include "upnpcpbdevicerepository.h"
+#include "upnpcpbsimpledevicedescription.h"
+#include "upnpcpbembeddeddevicedescription.h"
+#include "upnpcpbhttpmessagecontroller.h"
+#include "upnpcontenthandlerscontroller.h"
+#include "upnpcommonupnplits.h"
+#include "upnpcpstackrequestor.h"
+
+#define KLogFile _L("UPnPControlPoint.txt")
+#include <upnpcustomlog.h>
+
+// Time window reserved for single device discovery
+static const TInt KDeviceDiscoveryTimeout = 30000000;
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::NewL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpCpbDescriptionAgent* CUpnpCpbDescriptionAgent::NewL(
+ CUpnpControlPoint& aBaseCP,
+ MUpnpCpbHttpMessageController& aMessanger,
+ CUpnpCpbDeviceRepository& aRepository)
+ {
+ LOG_FUNC_NAME;
+ CUpnpCpbDescriptionAgent* self =
+ new (ELeave) CUpnpCpbDescriptionAgent(
+ aBaseCP, aMessanger, aRepository );
+
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::~CUpnpCpbDescriptionAgent
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CUpnpCpbDescriptionAgent::~CUpnpCpbDescriptionAgent()
+ {
+ LOG_FUNC_NAME;
+
+ iIncomingDevices.ResetAndDestroy();
+ iIncomingDevices.Close();
+
+ if (iTimer)
+ {
+ iTimer->Cancel();
+ }
+ delete iTimer;
+
+ iUuid.Close();
+ delete iSaxController;
+ delete iSimpleDiscoveryEngine;
+ delete iEmbeddedDiscoveryEngine;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::CUpnpCpbDescriptionAgent
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpCpbDescriptionAgent::CUpnpCpbDescriptionAgent(
+ CUpnpControlPoint& aBaseCP,
+ MUpnpCpbHttpMessageController& aMessanger,
+ CUpnpCpbDeviceRepository& aRepository )
+: iBaseCP( aBaseCP ), iMessanger( aMessanger ), iDeviceRepository( aRepository),
+ iPendingDiscovery( EFalse ), iDescriptionSession( KErrNotFound )
+ {
+ LOG_FUNC_NAME;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ConstructL
+// Second phase constructor
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::ConstructL()
+ {
+ LOG_FUNC_NAME;
+ iSimpleDiscoveryEngine =
+ CUpnpCpbSimpleDeviceDescription::NewL(iMessanger, iDeviceRepository);
+ iEmbeddedDiscoveryEngine =
+ CUpnpCpbEmbeddedDeviceDescription::NewL(iMessanger, iDeviceRepository);
+ // Sax paresr for device description
+ iSaxController = CUpnpContentHandlersController::NewL();
+
+ iTimer = CUpnpNotifyTimer::NewL(this);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::DeviceAliveNotificationL
+// New device found
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::DeviceAliveNotificationL( CUpnpDevice* aDevice )
+ {
+ LOG_FUNC_NAME;
+
+ TPtrC8 deviceType;
+ deviceType.Set( aDevice->DeviceType() );
+
+ if ( (iDeviceRepository.MatchTargetDevice(deviceType)
+ || (UpnpSSDP::KUPnPRootDevice().Find( deviceType ) != KErrNotFound))
+ && !iDeviceRepository.IsKnownDevice( aDevice->Uuid() ) )
+ {
+ CUpnpDevice* tmp = aDevice->CloneL();
+ CleanupStack::PushL( tmp );
+
+ if ( iPendingDiscovery )
+ {
+ iIncomingDevices.AppendL(tmp);
+ }
+ else
+ {
+ GetDeviceDescriptionL( tmp );
+ }
+
+ CleanupStack::Pop(tmp);
+ }
+ else
+ {
+ CUpnpDevice* device = iDeviceRepository.FindDevice( aDevice->Uuid() );
+ if ( device )
+ {
+ device->SetExpired( EFalse );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ProcessDeviceMessageL
+// Process device message
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::ProcessDeviceMessageL(
+ CUpnpHttpMessage* aHttpMessage )
+ {
+ if( iDescriptionSession != aHttpMessage->SessionId() )
+ {
+ return;
+ }
+
+ iDescriptionSession = KErrNotFound;
+ // No response
+ if ( !aHttpMessage->Is2xx() )
+ {
+ LOGS("CUpnpCpbDescriptionAgent::ProcessDeviceMessageL - "
+ "Request timed out. Max Retries reached. Ignoring device.");
+ if( iUuid.Length() )
+ {
+ iTimer->Cancel();
+ iPendingDiscovery = EFalse;
+ StopIgnoringUuidL(iUuid);
+ }
+ DiscoverNextDeviceL();
+ }
+ // Process description
+ else
+ {
+ ConstructAndValidateDeviceTreeL( aHttpMessage->Body( ),
+ aHttpMessage->Sender( ), aHttpMessage->SenderPath( ) );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ConstructAndValidateDeviceTreeL
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::ConstructAndValidateDeviceTreeL(
+ const TDesC8& aDeviceDescXml, const TInetAddr& aAddr,
+ const TDesC8& aDeviceDescPath )
+ {
+ CUpnpDevice* device = NULL;
+ TInt error;
+ if(iDeviceRepository.MatchTargetDevice(_L8("*")))
+ {
+ CUpnpDeviceDescription* deviceDescription =new CUpnpDeviceDescription();
+ TRAP( error, iSaxController->ParseDeviceL( aDeviceDescXml,deviceDescription ) );
+ if(!error)
+ {
+ CleanupStack::PushL( deviceDescription );
+ RBuf8 description;
+ if(deviceDescription->UrlBase().Length()!=0)
+ {
+ description.Create(aDeviceDescPath.Length()+deviceDescription->UrlBase().Length());
+ description.Copy(deviceDescription->UrlBase());
+ TInt firstSlash(aDeviceDescPath.Locate( KSlash8()[0] ) );
+ if(firstSlash==0)
+ description.Append( aDeviceDescPath.Mid( firstSlash+1,aDeviceDescPath.Length()-1 ) );
+ else
+ description.Append(aDeviceDescPath);
+ deviceDescription->SetDescriptionUrlL(description);
+ description.Close();
+ }
+ else
+ {
+ TBuf<25> ipBuf;
+ description.Create(KUrlMaxLength);
+ description.Copy(KHttp());
+
+ aAddr.Output ( ipBuf);
+ description.Append(ipBuf);
+ description.Append(_L8(":"));
+ ipBuf.Num(aAddr.Port());
+ description.Append(ipBuf);
+ description.Append(aDeviceDescPath);
+ deviceDescription->SetDescriptionUrlL(description);
+ description.Close();
+ }
+ CleanupStack::Pop(deviceDescription);
+ device=deviceDescription;
+ }
+ }
+ else
+ {
+ TRAP( error, device = iSaxController->ParseDeviceL( aDeviceDescXml ) );
+ }
+
+ if ( error || ( !device ) ) // Description is wrong
+ {
+ if( iUuid.Length() )
+ {
+ iTimer->Cancel();
+ iPendingDiscovery = EFalse;
+ StopIgnoringUuidL(iUuid);
+ }
+ DiscoverNextDeviceL();
+ return;
+ }
+
+ if ( aDeviceDescPath.Length() != 0 )
+ {
+ SetUrlBaseL( device, aDeviceDescPath );
+ }
+
+ // Device is invalid
+ if( !IsDeviceValid( device ) )
+ {
+ delete device;
+ if( iUuid.Length() )
+ {
+ iTimer->Cancel();
+ iPendingDiscovery = EFalse;
+ StopIgnoringUuidL(iUuid);
+ }
+ DiscoverNextDeviceL();
+ return;
+ }
+
+ // Check if device is know now
+ if( iDeviceRepository.IsKnownDevice( device->Uuid() ))
+ {
+ delete device;
+ iTimer->Cancel();
+ iPendingDiscovery = EFalse;
+ DiscoverNextDeviceL();
+ return;
+ }
+ // Is device partialy discovered
+ CUpnpDevice* oldDevice =
+ iDeviceRepository.FindIncompliteDevice( device->Uuid() );
+ if( oldDevice )
+ {
+ iDeviceRepository.RemoveDevice( oldDevice );
+ delete device;
+ device = oldDevice;
+ }
+
+ RPointerArray<CUpnpDevice> devices;
+ device->GetAllDevices( devices );
+ devices.AppendL( device );
+
+ CUpnpDevice::TUpnpDeviceNetwork network = FindNetworkForDeviceTree( devices );
+
+ for (TInt i = 0; i < devices.Count(); i++ )
+ {
+ devices[i]->SetAddress( aAddr );
+ devices[i]->SetDeviceNetwork( network );
+ }
+ devices.Reset();
+ devices.Close();
+
+ ChooseDesriptionProcesor(device);
+ HandleDiscoveryResultL(iDiscoveryEngine->DiscoverDeviceL(device));
+ }
+
+// -----------------------------------------------------------------------------
+// This function sets UrlBase value based on the relative path of the description URL
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::SetUrlBaseL(
+ CUpnpDevice* aDevice, const TDesC8& aPath )
+ {
+ if ( aDevice->UrlBase().Length( ) == 0 )
+ {
+ TInt firstSlash(aPath.Locate( KSlash8()[0] ) );
+ TInt lastSlash(aPath.LocateReverse( KSlash8()[0] ) );
+ if ( firstSlash == lastSlash )
+ {
+ aDevice->SetUrlBaseL( KSlash8( ) );
+ }
+ else
+ {
+ aDevice->SetUrlBaseL( aPath.Mid( firstSlash, lastSlash ) );
+ }
+ }
+ TPtrC8 baseURL(aDevice->UrlBase( ) );
+
+ RPointerArray<CUpnpDevice> devices;
+ aDevice->GetAllDevices( devices );
+ CleanupClosePushL( devices );
+
+ for ( TInt i(0); i< devices.Count( ); i++ )
+ {
+ if ( devices[i]->UrlBase().Length( ) == 0 )
+ {
+ devices[i]->SetUrlBaseL( baseURL );
+ }
+ }
+ CleanupStack::PopAndDestroy( &devices );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ChooseDesriptionProcesor
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::ChooseDesriptionProcesor(CUpnpDevice* aDevice)
+ {
+ if( aDevice->DeviceList().Count() )
+ {
+ iDiscoveryEngine = iEmbeddedDiscoveryEngine;
+ }
+ else
+ {
+ iDiscoveryEngine = iSimpleDiscoveryEngine;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::FindNetworkForDeviceTree
+// -----------------------------------------------------------------------------
+//
+CUpnpDevice::TUpnpDeviceNetwork CUpnpCpbDescriptionAgent::FindNetworkForDeviceTree(
+ RPointerArray<CUpnpDevice>& aDevices )
+ {
+ CUpnpDevice::TUpnpDeviceNetwork network = CUpnpDevice::EUnknown;
+ for (TInt i = 0; i < aDevices.Count(); i++ )
+ {
+ CUpnpDevice* ssdpDevice =
+ iDeviceRepository.RemoveIncomingDevice( aDevices[i]->Uuid() );
+ if ( ssdpDevice )
+ {
+ aDevices[i]->SetExpired( EFalse );
+ network = ssdpDevice->DeviceNetwork();
+ delete ssdpDevice;
+ if ( network != CUpnpDevice::EUnknown )
+ {
+ break;
+ }
+ }
+ }
+ return network;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ProcessServiceMessageL
+// Process service message
+// -----------------------------------------------------------------------------
+//
+ void CUpnpCpbDescriptionAgent::ProcessServiceMessageL(
+ CUpnpHttpMessage* aHttpMessage)
+ {
+ if(iDiscoveryEngine)
+ {
+ HandleDiscoveryResultL(
+ iDiscoveryEngine->ServiceDescriptionL(aHttpMessage) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::DiscoverNextDeviceL
+// Start next device discovery
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::DiscoverNextDeviceL()
+ {
+ // search for new target device
+ while( iIncomingDevices.Count() > 0 )
+ {
+ CUpnpDevice* tempDevice = iIncomingDevices[0];
+ iIncomingDevices.Remove(0);
+ CleanupStack::PushL( tempDevice );
+
+ CUpnpDevice* tempDevice2 =
+ iDeviceRepository.FindDevice( tempDevice->Uuid() );
+
+ if( !tempDevice2 )
+ {
+ GetDeviceDescriptionL( tempDevice );
+ CleanupStack::Pop( tempDevice );
+ break;
+ }
+ else
+ {
+ tempDevice2->SetExpired( EFalse );
+ CleanupStack::PopAndDestroy( tempDevice );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::GetDeviceDescriptionL
+// Send get message
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::GetDeviceDescriptionL( CUpnpDevice* aDevice )
+ {
+ iUuid.Close();
+ iUuid.CreateL( aDevice->Uuid());
+ if( iDiscoveryEngine )
+ {
+ iDiscoveryEngine->DeleteTargetDevice();
+ iDiscoveryEngine = NULL;
+ }
+
+ iDeviceRepository.AddIncomingDeviceL( aDevice );
+
+ iTimer->Start( KDeviceDiscoveryTimeout );
+ iPendingDiscovery = ETrue;
+
+ iDescriptionSession = iMessanger.GetDeviceDescriptionL( aDevice );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::HandleDiscoveryResultL
+// Function processing disscovery result
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::HandleDiscoveryResultL(TInt aResult)
+ {
+ if(aResult == KErrNotFound || aResult == KDisscoveryInProgress)
+ {
+ return;
+ }
+ iTimer->Cancel();
+ iPendingDiscovery = EFalse;
+
+ TBool result;
+ if(aResult == KDisscoveryFinished)
+ {
+ result = CopyResult();
+ if(!result)
+ {
+ StopIgnoringUuidL(iDiscoveryEngine->FailedUuidsL());
+ }
+ else
+ {
+ iDiscoveryEngine->NullTargetDevice();
+ ReportDiscoveredDevicesL();
+ }
+ DiscoverNextDeviceL();
+ }
+ else if(aResult == KDisscoveryIncorrect)
+ {
+ result = CopyResult();
+ if(!result)
+ {
+ StopIgnoringUuidL(iDiscoveryEngine->GetTargetDevice()->Uuid());
+ }
+ else
+ {
+ StopIgnoringUuidL(iDiscoveryEngine->FailedUuidsL());
+ CUpnpDevice* dev = iDiscoveryEngine->GetIncompliteRootDevice();
+ if(dev)
+ {
+ iDeviceRepository.AddIncompliteDeviceL(dev);
+ }
+ iDiscoveryEngine->NullTargetDevice();
+ ReportDiscoveredDevicesL();
+ }
+ DiscoverNextDeviceL();
+ }
+ };
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::CopyResultL
+// Copy devices to repository
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpCpbDescriptionAgent::CopyResult()
+ {
+ TRAPD(error, CopyResultL());
+ if(error)
+ {
+ RPointerArray<CUpnpDevice> devices;
+ iDiscoveryEngine->GetTargetDevice()->GetAllDevices(devices);
+ for (TInt i(0); i < devices.Count(); i++)
+ {
+ iDeviceRepository.RemoveDevice(devices[i]);
+ }
+ iDeviceRepository.RemoveDevice(iDiscoveryEngine->GetTargetDevice());
+ devices.Close();
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::CopyResultL
+// Copy devices to repository
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::CopyResultL()
+ {
+ RPointerArray<CUpnpDevice> devices;
+ CleanupClosePushL(devices);
+ iDiscoveryEngine->GetUninterestingDeviceL(devices, ETrue);
+ iDeviceRepository.AddUninterestingDevicesL(devices);
+ devices.Reset();
+ iDiscoveryEngine->GetUnnededDeviceL(devices, ETrue);
+ iDeviceRepository.AddUnneddedDevicesL(devices);
+ devices.Reset();
+ iDiscoveryEngine->GetDiscoveredDeviceL(devices, ETrue);
+ iDeviceRepository.AddDiscoveredDevicesL(devices);
+ CleanupStack::PopAndDestroy(&devices);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::ReportDiscoveredDevicesL
+// Report discovered devices to the client
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::ReportDiscoveredDevicesL()
+ {
+ RPointerArray<CUpnpDevice> devices;
+ CleanupClosePushL(devices);
+ iDiscoveryEngine->GetDiscoveredDeviceL(devices);
+ for (TInt i(0); i < devices.Count(); i++)
+ {
+ iBaseCP.DeviceDiscovered(devices[i]);
+ }
+ CleanupStack::PopAndDestroy(&devices);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::StopIgnoringUidL
+// Send stop filtering message to MH
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::StopIgnoringUuidL(const TDesC8& aUuids)
+ {
+ iMessanger.StopIgnoringUuidL(aUuids);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::IsDeviceValid
+// Check if device is valid
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpCpbDescriptionAgent::IsDeviceValid( CUpnpDevice* aDevice )
+ {
+ const TDesC8& targetUuid = aDevice->Uuid();
+ return !( aDevice->DeviceType() == KNullDesC8()
+ || targetUuid == KNullDesC8() );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpCpbDescriptionAgent::TimerEventL
+// Callback function
+// -----------------------------------------------------------------------------
+//
+void CUpnpCpbDescriptionAgent::TimerEventL( CUpnpNotifyTimer* aTimer )
+ {
+ if( !(aTimer->iStatus == KErrNone) )
+ {
+ return;
+ }
+
+ if ( iPendingDiscovery )
+ {
+ iPendingDiscovery = FALSE;
+ if(iDiscoveryEngine)
+ {
+ StopIgnoringUuidL(iDiscoveryEngine->FailedUuidsL());
+ DiscoverNextDeviceL();
+ }
+ else
+ {
+ if( iUuid.Length() )
+ {
+ StopIgnoringUuidL(iUuid);
+ }
+ }
+ }
+ }
+
+// End of File