Updated the SIS package, there was some BC issue with the earlier version. Also updated the platform UID to S^3 version.
/*
* Copyright (c) 2006-2009 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: AVController server
*
*/
// INCLUDE FILES
// System
#include <e32svr.h>
#include <f32file.h>
// upnp stack
#include <upnpdevice.h>
#include <upnpsettings.h>
// dlnasrv / avcontroller api
#include "upnpavcontrollerglobals.h"
// dlnasrv / internal api's
#include "upnpconnectionmonitor.h"
// dlnasrv / avcontroller server internal
#include "upnpavcontrollerserver.h"
#include "upnpavcontrollersession.h"
#include "upnpavcontrolpoint.h"
#include "upnpavdispatcher.h"
#include "upnpdevicerepository.h"
#include "upnpavdeviceextended.h"
#include "upnpaverrorhandler.h"
#include "upnpavcpstrings.h"
_LIT( KComponentLogfile, "upnpavcontrollerserver.txt" );
#include "upnplog.h"
using namespace UpnpAVCPStrings;
// CONSTANTS
_LIT8( KUPnPRootDevice, "upnp:rootdevice" );
const TUint KMyRangeCount = 3;
const TInt KMyRanges[ KMyRangeCount ] =
{
0, // numbers 0-18
18, // numbers 18-EAVControllerRqstLast
EAVControllerRqstLast // numbers EAVControllerRqstLast-KMaxInt
};
const TUint8 KMyElementsIndex[ KMyRangeCount ] =
{
0,
1,
CPolicyServer::ENotSupported
};
const CPolicyServer::TPolicyElement KMyElements[] =
{
{_INIT_SECURITY_POLICY_C3(ECapabilityNetworkServices,
ECapabilityReadUserData, ECapabilityWriteUserData ),
CPolicyServer::EFailClient },
{_INIT_SECURITY_POLICY_C1(ECapabilityNetworkServices),
CPolicyServer::EFailClient}
};
const CPolicyServer::TPolicy KMyPolicy =
{
CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
KMyRangeCount,
KMyRanges,
KMyElementsIndex,
KMyElements,
};
// ============================ MEMBER FUNCTIONS ============================
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::CUpnpAVControllerServer
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUpnpAVControllerServer::CUpnpAVControllerServer( TInt aPriority ):
CPolicyServer( aPriority, KMyPolicy ),
iShutdownTimeoutValue( KTimerCycle10 ),
iState( EStateUndefined )
{
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ConstructL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::ConstructL()
{
__LOG( "CUpnpAVControllerServer::ConstructL" );
ChangeState( EStateStartingServer );
__LOG( "ConstructL - Starting server" );
// create av dispatcher
iDispatcher = CUPnPAVDispatcher::NewL( *this );
// create av control point
iAVControlPoint = CUpnpAVControlPoint::NewL( *iDispatcher );
// create device repository
iDeviceRepository = CUPnPDeviceRepository::NewL( *iAVControlPoint );
iUpnpSettings = CUpnpSettings::NewL( KCRUidUPnPStack );
iUpnpSettings->Get( CUpnpSettings::KUPnPStackIapId, iIAP );
iMonitor = CUPnPConnectionMonitor::NewL( iIAP );
iMonitor->SetObserver( *this );
StartL( KAVControllerName );
iServerTimer = CUPnPAVTimer::NewL( *this,
CUPnPAVTimer::ETimerServerShutdown );
iServerTimer->Start( iShutdownTimeoutValue );
iIconDownloader = CUpnpDeviceIconDownloader::NewL( *this, iIAP );
__LOG( "CUpnpAVControllerServer::ConstructL - Finished" );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::StartUpL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::StartUpL()
{
__LOG( "CUpnpAVControllerServer::StartUpL" );
if( iState == EStateStartingServer )
{
ChangeState( EStateStartingControlPoint );
__LOG( "StartUpL - Starting control point" );
// start SSPD search
TInt err = KErrNone;
TRAP( err, iAVControlPoint->StartUpL() );
if( err == KErrNone )
{
__LOG( "StartUpL - Searching root device" );
iAVControlPoint->SearchL( KUPnPRootDevice );
ChangeState( EStateRunning );
}
else
{
iShutdownTimeoutValue = 0;
User::Leave( err );
}
}
else if( iState == EStateShuttingDown )
{
__LOG( "StartUpL - Wlan disconnected or shutting down, leave" );
User::Leave( KErrDisconnected );
}
else if( iState == EStateStartingControlPoint )
{
__LOG( "StartUpL - Already starting control point" );
}
else
{
__LOG( "StartUpL - Server already running" );
}
__LOG( "StartUpL - Completed" );
}
void CUpnpAVControllerServer::CancelStartUp()
{
__LOG( "CUpnpAVControllerServer::CancelStartUp" );
// Cancel can occur only when the av controller instance is deleted
// right after the asyncronous part of the construction has been
// started. There is no proper way to cancel, but we can set the
// shutdown timer to 0, so the server will shutdown immidiately.
if( iSessionCount <= 1 )
{
iShutdownTimeoutValue = 0;
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::NewLC
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUpnpAVControllerServer* CUpnpAVControllerServer::NewLC()
{
CUpnpAVControllerServer* self = new( ELeave )
CUpnpAVControllerServer( EPriorityNormal );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::~CUpnpAVControllerServer
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUpnpAVControllerServer::~CUpnpAVControllerServer()
{
__LOG( "CUpnpAVControllerServer::~CUpnpAVControllerServer" );
delete iAVControlPoint;
delete iDispatcher;
delete iDeviceRepository;
delete iMonitor;
delete iServerTimer;
delete iUpnpSettings;
delete iIconDownloader;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::NewSessionL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CSession2* CUpnpAVControllerServer::NewSessionL( const TVersion& aVersion,
const RMessage2& /*aMessage*/ ) const
{
__LOG( "CUpnpAVControllerServer::NewSessionL" );
TInt err = KErrNone;
// check if the server is shutting down
if( iState == EStateShuttingDown )
{
__LOG( "NewSessionL - server shutting down, no new sessions are allowed at this point" );
err = KErrDisconnected;
}
// Check we're the right version
else if ( !User::QueryVersionSupported( TVersion(
KAVControllerMajorVersionNumber,
KAVControllerMinorVersionNumber,
KAVControllerBuildVersionNumber ),
aVersion ) )
{
__LOG( "NewSessionL - incorrect client version" );
err = KErrNotSupported;
}
// leave if error
User::LeaveIfError( err );
// Make new session
return CUpnpAVControllerSession::NewL(
const_cast<CUpnpAVControllerServer&>( *this ) );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ActionResponseL
// From MUpnpAVControlPointObserver
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::ActionResponseL( CUpnpAction* aAction )
{
if (aAction->Name().Compare( KGetProtocolInfo ) == 0)
{
const TDesC8& uuid = aAction->Service().Device().Uuid();
CmProtocolInfoResponse(
uuid,
aAction->Error(),
aAction->ArgumentValue( KSource ),
aAction->ArgumentValue( KSink )
);
iDispatcher->UnRegister(aAction->SessionId());
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::StateUpdatedL
// From MUpnpAVControlPointObserver
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::StateUpdatedL( CUpnpService* /*aService*/ )
{
// No implementation required
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::HttpResponseL
// From MUpnpAVControlPointObserver
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::HttpResponseL( CUpnpHttpMessage* /*aMessage*/ )
{
// No implementation required
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceDiscoveredL
// From MUpnpAVControlPointObserver
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceDiscoveredL( CUpnpDevice* /*aDevice*/ )
{
// No implementation required
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceDisappearedL
// From MUpnpAVControlPointObserver
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceDisappearedL(CUpnpDevice* /*aDevice*/)
{
// No implementation required
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::UPnPAVTimerCallback
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::UPnPAVTimerCallback(
CUPnPAVTimer::TAVTimerType aType )
{
__LOG( "CUpnpAVControllerServer::UPnPAVTimerCallback" );
if( aType == CUPnPAVTimer::ETimerServerShutdown )
{
ChangeState( EStateShutDown );
CActiveScheduler::Stop();
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ConnectionLost
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::ConnectionLost( TBool /*aUserOriented*/ )
{
__LOG( "CUpnpAVControllerServer::ConnectionLost" );
iShutdownTimeoutValue = 0; // Set shutdown timer value to 0, we want to
// shut down the server immidiately after the last session has been
// closed
if( iState == EStateRunning && iDeviceRepository )
{
__LOG( "ConnectionLost - Server running" );
iDeviceRepository->ConnectionLost();
CSession2* s;
iSessionIter.SetToFirst();
while ( ( s = iSessionIter++ ) != NULL )
{
CUpnpAVControllerSession* sess =
static_cast<CUpnpAVControllerSession*>(s);
if( sess )
{
sess->ConnectionLost();
}
};
ChangeState( EStateShuttingDown );
}
else if( iState == EStateStartingServer )
{
__LOG( "ConnectionLost - Server starting" );
ChangeState( EStateShuttingDown );
}
// If don't have any clients connect to server and current WLAN connection
// is lost, we want to shut down the server immidiately.
if ( iSessionCount <= 0 )
{
if ( iServerTimer->IsActive() )
{
iServerTimer->Cancel();
}
iServerTimer->Start( iShutdownTimeoutValue );
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::RunError
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
TInt CUpnpAVControllerServer::RunError( TInt aError )
{
__LOG2( "CUpnpAVControllerServer::RunError msg: %d err: %d",
Message().Function(), aError );
if ( aError == KErrBadDescriptor )
{
PanicClient( Message(), EAVControllerServerBadDescriptor );
}
else if ( !Message().IsNull() )
{
Message().Complete( aError );
}
// The leave will result in an early return from CServer::RunL(),
// skipping the call to request another message. So do that now in order
// to keep the server running.
ReStart();
// Handled the error fully
return KErrNone;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::PanicClient
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::PanicClient(const RMessage2& aMessage,
TAVControllerServerPanic aPanic)
{
__LOG1( "CUpnpAVControllerServer::PanicClient %d", aPanic );
aMessage.Panic( KAVControllerName, aPanic );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::PanicServer
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::PanicServer(TAVControllerServerPanic aPanic)
{
__LOG1( "CUpnpAVControllerServer::PanicServer %d", aPanic );
User::Panic( KAVControllerName, aPanic );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ThreadFunctionL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::ThreadFunctionL()
{
__LOG( "CUpnpAVControllerServer::ThreadFunctionL" );
// Construct active scheduler
CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
CleanupStack::PushL( activeScheduler );
// Install active scheduler
// We don't need to check whether an active scheduler is already
// installed
// as this is a new thread, so there won't be one
CActiveScheduler::Install( activeScheduler );
// Construct our server
CUpnpAVControllerServer* server = CUpnpAVControllerServer::NewLC();
RProcess::Rendezvous( KErrNone );
// Start handling requests
CActiveScheduler::Start();
CleanupStack::PopAndDestroy( server );
CleanupStack::PopAndDestroy( activeScheduler );
__LOG( "CUpnpAVControllerServer::ThreadFunctionL end" );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ThreadFunction
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
TInt CUpnpAVControllerServer::ThreadFunction()
{
__LOG( "CUpnpAVControllerServer::ThreadFunction" );
__UHEAP_MARK;
User::RenameThread(KAVControllerThreadName);
CTrapCleanup* cleanupStack = CTrapCleanup::New();
if ( !(cleanupStack) )
{
PanicServer( EAVControllerServerCreateTrapCleanup );
}
TRAPD( err, ThreadFunctionL() );
if ( err != KErrNone )
{
__LOG1( "ThreadFunction, creation failed: %d", err );
//PanicServer( EAVControllerServerSrvCreateServer );
}
delete cleanupStack;
cleanupStack = NULL;
__UHEAP_MARKEND;
__LOG1( "CUpnpAVControllerServer::ThreadFunction end %d", err );
return err;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::IncrementSessions
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::IncrementSessions()
{
__LOG2( "CUpnpAVControllerServer::IncrementSessions, %d, %d",
iSessionCount, iState );
iSessionCount++;
if( iServerTimer->IsActive() )
{
iServerTimer->Cancel();
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DecrementSessions
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DecrementSessions()
{
__LOG2( "CUpnpAVControllerServer::DecrementSessions, %d, %d",
iSessionCount, iState );
iSessionCount--;
if( iState != EStateShutDown )
{
if ( iSessionCount <= 0 )
{
if( iServerTimer->IsActive() )
{
iServerTimer->Cancel();
}
iServerTimer->Start( iShutdownTimeoutValue );
}
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceDiscoveredL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceDiscoveredL( CUpnpDevice& aDevice )
{
__LOG( "CUpnpAVControllerServer::DeviceDiscoveredL" );
iDeviceRepository->AddDeviceL( aDevice );
CUpnpAction* action = iAVControlPoint->CreateActionLC(
&aDevice, KConnectionManager, KGetProtocolInfo );
iAVControlPoint->SendL( action ); // takes ownership
CleanupStack::Pop( action );
iDispatcher->RegisterL( action->SessionId(), *this );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceDisappearedL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceDisappearedL( CUpnpDevice& aDevice )
{
__LOG( "CUpnpAVControllerServer::DeviceDisappearedL" );
// Get a corresponding device from the device repository
CUpnpAVDeviceExtended& tmp = iDeviceRepository->FindDeviceL(
aDevice.Uuid() );
// Let the clients know about the disappeared device
CSession2* s;
iSessionIter.SetToFirst();
while ( ( s = iSessionIter++ ) != NULL )
{
CUpnpAVControllerSession* sess =
static_cast<CUpnpAVControllerSession*>(s);
if( sess )
{
sess->DeviceDisappearedL( tmp );
}
};
// Remove from the device repository
TPtrC8 uuid( aDevice.Uuid() );
iDeviceRepository->Remove( uuid );
// Ensure that icon download is canceled
iIconDownloader->CancelDownload( uuid );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceDisappearedL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceDisappearedL( const TDesC8& aUuid )
{
__LOG( "CUpnpAVControllerServer::DeviceDisappearedL uid" );
// Get a corresponding device from the device repository
CUpnpAVDeviceExtended& tmp = iDeviceRepository->FindDeviceL(
aUuid );
// Let the clients know about the disappeared device
CSession2* s;
iSessionIter.SetToFirst();
while ( ( s = iSessionIter++ ) != NULL )
{
CUpnpAVControllerSession* sess =
static_cast<CUpnpAVControllerSession*>( s );
if ( sess )
{
sess->DeviceDisappearedL( tmp );
}
}
// Remove from the device repository
iDeviceRepository->Remove( aUuid );
// Ensure that icon download is canceled
iIconDownloader->CancelDownload( aUuid );
__LOG( "CUpnpAVControllerServer::DeviceDisappearedL uid End" );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::CmProtocolInfoResponse
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::CmProtocolInfoResponse( const TDesC8& aUuid,
TInt aErr, const TDesC8& aSource,
const TDesC8& aSink )
{
__LOG1( "CUpnpAVControllerServer::CmProtocolInfoResponse, \
aErr = %d", aErr );
aErr = UPnPAVErrorHandler::ConvertToSymbianErrorCode( aErr,
EUPnPConnectionManagerError );
if( aErr == KErrNone )
{
CUpnpAVDeviceExtended* dev = NULL;
TRAPD( err, dev = &iDeviceRepository->AddProtocolInfoL(
aUuid, aSource, aSink ) );
if( err == KErrNone )
{
// Device discovered and protocolinfo was retrieved successfully
// Start icon download if icon url is defined
TPtrC8 iconUrl( dev->IconUrl() );
if ( iconUrl.Length() > 0 )
{
TRAP_IGNORE( iIconDownloader->StartDownloadL( dev->Uuid(), iconUrl ) );
}
CSession2* s;
iSessionIter.SetToFirst();
while ( ( s = iSessionIter++ ) != NULL )
{
CUpnpAVControllerSession* sess =
static_cast<CUpnpAVControllerSession*>(s);
if( sess )
{
TRAP_IGNORE( sess->DeviceDiscoveredL( *dev ) );
}
};
}
else
{
// Could not add protocolinfo, it's invalid or corrupted
// Device cannot be used
HandleFailedProtocolInfoResponse( aUuid );
}
}
else
{
// A problem occured fetching protocolinfo
// Device cannot be used
HandleFailedProtocolInfoResponse( aUuid );
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::TransferDeviceIconFileToClientL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::TransferDeviceIconFileToClientL(
const RMessage2& aMessage, TInt aSlot, const TDesC8& aDeviceUuid )
{
return iIconDownloader->TransferFileToClientL( aMessage, aSlot, aDeviceUuid );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::HandleFailedProtocolInfoResponse
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::HandleFailedProtocolInfoResponse(
const TDesC8& aUuid )
{
__LOG( "CUpnpAVControllerServer::HandleFailedProtocolInfoResponse" );
iDeviceRepository->Remove( aUuid );
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ChangeState
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::ChangeState( TAVControllerServerState aState )
{
__LOG( "CUpnpAVControllerServer::ChangeState" );
if( iState != aState )
{
__LOG2( "ChangeState: Changing state [%d] -> [%d]",
iState, aState );
iState = aState;
}
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::ControlPoint
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUpnpAVControlPoint& CUpnpAVControllerServer::ControlPoint()
{
return *iAVControlPoint;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::Dispatcher
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUPnPAVDispatcher& CUpnpAVControllerServer::Dispatcher()
{
return *iDispatcher;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceRepository
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
CUPnPDeviceRepository& CUpnpAVControllerServer::DeviceRepository()
{
return *iDeviceRepository;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::IAP
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
TInt CUpnpAVControllerServer::IAP()
{
return iIAP;
}
// --------------------------------------------------------------------------
// CUpnpAVControllerServer::DeviceIconDownloadedL
// See upnpavcontrollerserver.h
// --------------------------------------------------------------------------
void CUpnpAVControllerServer::DeviceIconDownloadedL( const TDesC8& aDeviceUuid,
TInt aError )
{
__LOG( "CUpnpAVControllerServer::DeviceIconDownloadedL" );
if ( aError == KErrNone )
{
// Get a corresponding device from the device repository
CUpnpAVDeviceExtended& tmp = iDeviceRepository->FindDeviceL(
aDeviceUuid );
// Let the clients know about downloaded icon
CSession2* s;
iSessionIter.SetToFirst();
while ( ( s = iSessionIter++ ) != NULL )
{
CUpnpAVControllerSession* sess =
static_cast<CUpnpAVControllerSession*>( s );
if ( sess )
{
sess->DeviceIconDownloadedL( tmp );
}
}
}
__LOG( "CUpnpAVControllerServer::DeviceIconDownloadedL End" );
}
// ============================= LOCAL FUNCTIONS ============================
// --------------------------------------------------------------------------
// E32Main entry point.
// Returns: KErrNone
// --------------------------------------------------------------------------
TInt E32Main()
{
return CUpnpAVControllerServer::ThreadFunction();
}
// End of File