omadrm/drmengine/roapstorage/src/RoapStorageServer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:27 +0200
changeset 0 95b198f216e5
child 18 8a03a285ab14
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2004 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:  
*
*/



// INCLUDE FILES
#include <e32std.h>

#ifdef RD_MULTIPLE_DRIVE
#include <DriveInfo.h>
#endif

#include "RoapStorageServer.h"
#include "DRMContextDB.h"
#include "RoapLog.h"
#include "drmroapclientserver.h"
#include "drmcommonclientserver.h"
#include "drmkeystorage.h"

// EXTERNAL DATA STRUCTURES
// EXTERNAL FUNCTION PROTOTYPES  
// CONSTANTS
// MACROS


// LOCAL CONSTANTS AND MACROS
const TUint8 KMaxStartTries = 5;
const TInt KWaitingTime = 1000000; // 10 secs

_LIT( KRoapStorageThread, "RoapStorageServer" );

#ifdef RD_MULTIPLE_DRIVE
_LIT( KRIContextFileName, "%c:\\private\\101F51F2\\ricontexts.dat" );
_LIT( KDomainContextFileName, "%c:\\private\\101F51F2\\domaincontexts.dat" );
// File names and paths for importing keys
_LIT( KImportDir, "%c:\\private\\101F51F2\\import\\" );
_LIT( KInputFilePattern, "%c:\\private\\101F51F2\\import\\SigningCert*" );
_LIT( KDeviceKeyFileName, "%c:\\private\\101F51F2\\import\\DevicePrivateKey.der" );
_LIT( KDeviceCertFileName, "%c:\\private\\101F51F2\\import\\DeviceCert.der" );
#else
// File names and paths for importing keys
_LIT( KImportDir, "c:\\private\\101F51F2\\import\\" );
_LIT( KInputFilePattern, "c:\\private\\101F51F2\\import\\SigningCert*" );
_LIT( KDeviceKeyFileName, "c:\\private\\101F51F2\\import\\DevicePrivateKey.der" );
_LIT( KDeviceCertFileName, "c:\\private\\101F51F2\\import\\DeviceCert.der" );
#endif

// MODULE DATA STRUCTURES
using Roap::KServerMajorVersion;
using Roap::KServerMinorVersion;
using Roap::KServerBuildVersion;

// LOCAL FUNCTION PROTOTYPES
LOCAL_C TInt StartRoapServer( RSemaphore& aClientSem );

// FORWARD DECLARATIONS

// ============================= LOCAL FUNCTIONS ===============================


// -----------------------------------------------------------------------------
// Function StartRoapServer().
// This function starts the actual server under TRAP harness and starts
// waiting for connections. This function returns only if there has been
// errors during server startup or the server is stopped for some reason.
// 
// Returns: TInt: Symbian OS error code.
// -----------------------------------------------------------------------------
LOCAL_C TInt StartRoapServer( RSemaphore& aClientSem ) 

    {
    TInt error = KErrNone;
    CRoapStorageServer* server = NULL;
    TUint8 count = 0;

    do 
        {
        ++count;
        TRAP( error, ( server = CRoapStorageServer::NewL() ) );
        if ( error ) 
           {
           User::After( TTimeIntervalMicroSeconds32(KWaitingTime) );
           }
       
        } while( error && ( count <= KMaxStartTries ) );
    
    if( error ) 
        {
        return error;
        }
        
    // Release the semaphore...
    aClientSem.Signal();
    aClientSem.Close();
    
    // Start waiting for connections
    CActiveScheduler::Start();
    
    // Delete CRoapStorageServer
    delete server;
    
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// Function ReadFileL().
// Read a file into a buffer
// -----------------------------------------------------------------------------
LOCAL_C void ReadFileL( RFs& aFs, HBufC8*& aContent, const TDesC& aName )
	{	
	TInt size = 0;
	RFile file;
	
	User::LeaveIfError( file.Open( aFs, aName, EFileRead ) );
	CleanupClosePushL( file );
    User::LeaveIfError( file.Size( size ) );
    aContent = HBufC8::NewLC( size );
    TPtr8 ptr( aContent->Des() );
    User::LeaveIfError( file.Read( ptr, size) );
    CleanupStack::Pop(); // aContent
	CleanupStack::PopAndDestroy(); // file
	}

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CRoapStorageServer::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CRoapStorageServer* CRoapStorageServer::NewL()
    {
    CRoapStorageServer* self = new( ELeave ) CRoapStorageServer();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self ); 
    return self;
    }

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
CRoapStorageServer::~CRoapStorageServer() 
    {
    iRFs.Close();
    delete iRoapStorage;
    }

// -----------------------------------------------------------------------------
// CRoapStorageServer::RunErrorL
// From CActive. Complete the request and restart the scheduler.
// -----------------------------------------------------------------------------
//
TInt CRoapStorageServer::RunError( TInt aError ) 
    {
    // Inform the client.
    Message().Complete( aError );
    // Restart the scheduler.
    ReStart();
    // Error handled.
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CRoapStorageServer::NewSessionL
// Called when a client requires a new instance.
// -----------------------------------------------------------------------------
CSession2* CRoapStorageServer::NewSessionL(
    const TVersion& aVersion,
    const RMessage2& /*aMessage*/) const
    {
    RThread client;
    // Check that the versions are compatible.
    if ( ! User::QueryVersionSupported( TVersion( KServerMajorVersion,
                                                  KServerMinorVersion,
                                                  KServerBuildVersion ), 
                                        aVersion ) ) 
        {
        // Sorry, no can do.
        User::Leave( KErrNotSupported );
        }
    return CRoapStorageSession::NewL();
    }

// -----------------------------------------------------------------------------
// CRoapStorageServer::CRoapStorageServer
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CRoapStorageServer::CRoapStorageServer() : 
    CServer2( EPriorityStandard ),
    iRoapStorage( NULL )
    {
    // Nothing
    }
    
// -----------------------------------------------------------------------------
// CRoapStorageServer::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CRoapStorageServer::ConstructL() 
    {
    TInt err = KErrNone;
    
    User::RenameThread( KRoapStorageThread );
    StartL( Roap::KServerName );
    User::LeaveIfError(iRFs.Connect());
    
#ifndef RD_MULTIPLE_DRIVE
    
    iRoapStorage = CDRMContextDB::NewL( KRIContextFile(), 
                                        KDomainContextFile(),
                                        iRFs );
    
#else //RD_MULTIPLE_DRIVE
    
    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
	iRFs.DriveToChar( driveNumber, driveLetter );
	
	TFileName riContextFile;
	riContextFile.Format( KRIContextFileName, (TUint)driveLetter );
    
    TFileName domainContextFile;
	domainContextFile.Format( KDomainContextFileName, (TUint)driveLetter );
    
    iRoapStorage = CDRMContextDB::NewL( riContextFile, 
                                        domainContextFile,
                                        iRFs );
    
#endif
    
    TRAP( err, ImportKeysL() );
    }
    
// -----------------------------------------------------------------------------
// CRoapStorageServer::ContextDB
// Return the internal ROAP storage object
// -----------------------------------------------------------------------------
//       
CDRMContextDB* CRoapStorageServer::ContextDB()
    {
    return iRoapStorage;
    }

// -----------------------------------------------------------------------------
// CRoapStorageServer::ImportKeys
// Import keys which are stored in the import directory into the private
// directory. Only one key pair plus assocated certificates can be imported
// at a time. The file names are DevicePrivateKey.der, DeviceCert.der and
// SigningCertXX.der.
// -----------------------------------------------------------------------------
//       
void CRoapStorageServer::ImportKeysL()
    {
    MDrmKeyStorage* storage = NULL; 
    HBufC8* privateKey = NULL;
    HBufC8* cert = NULL;
    RArray<TPtrC8> certChain;
    RPointerArray<HBufC8> buffers;
    TFileName fileName;
    RFile file;
    TInt i;
    CDir* dir = NULL;
    TInt err = KErrNone;
    
    __UHEAP_MARK;
    LOG( _L( "CRoapStorageServer::ImportKeysL" ) );
    CleanupClosePushL( buffers );
    CleanupClosePushL( certChain );
    
#ifndef RD_MULTIPLE_DRIVE
    
    ReadFileL( iRFs, privateKey, KDeviceKeyFileName );
    
#else //RD_MULTIPLE_DRIVE
    
    TFileName tempPath;
    TFileName tempPath2;
    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
	iRFs.DriveToChar( driveNumber, driveLetter );
	
	tempPath.Format( KDeviceKeyFileName, (TUint)driveLetter );
    
    ReadFileL( iRFs, privateKey, tempPath );
    
#endif
    
    CleanupStack::PushL( privateKey );
    
#ifndef RD_MULTIPLE_DRIVE
    
    ReadFileL( iRFs, cert, KDeviceCertFileName );
    
#else //RD_MULTIPLE_DRIVE
    
	tempPath2.Format( KDeviceCertFileName, (TUint)driveLetter );
    
    ReadFileL( iRFs, cert, tempPath2 );
    
#endif
    
    CleanupStack::PushL( cert );
    buffers.AppendL( cert );
    
#ifndef RD_MULTIPLE_DRIVE
    
    iRFs.Delete( KDeviceKeyFileName );
    iRFs.Delete( KDeviceCertFileName );
    
#else //RD_MULTIPLE_DRIVE
    
	iRFs.Delete( tempPath );
    iRFs.Delete( tempPath2 );
    
#endif
    
#ifndef RD_MULTIPLE_DRIVE
    
    User::LeaveIfError( iRFs.GetDir( KInputFilePattern, KEntryAttNormal,
        ESortByName, dir ) );
    
#else //RD_MULTIPLE_DRIVE
    
	tempPath.Format( KInputFilePattern, (TUint)driveLetter );
    
    User::LeaveIfError( iRFs.GetDir( tempPath, KEntryAttNormal,
        ESortByName, dir ) );
    
#endif
    
    CleanupStack::PushL( dir );
    
    for ( i = 0; i < dir->Count(); i++ )
        {
        
#ifndef RD_MULTIPLE_DRIVE
    
        fileName.Copy( KImportDir );
    
#else //RD_MULTIPLE_DRIVE
    
	    tempPath.Format( KImportDir, (TUint)driveLetter );
        
        fileName.Copy( tempPath );
    
#endif
        
        fileName.Append( (*dir)[i].iName );
        ReadFileL( iRFs, cert, fileName );
        CleanupStack::PushL( cert );
        buffers.AppendL( cert );
        
        iRFs.Delete( fileName );
        }
    for ( i = 0; i < buffers.Count(); i++ )
        {
        certChain.AppendL( *( buffers[i] ) );
        }
    storage = DrmKeyStorageNewL();
    TRAP( err, storage->ImportDataL( *privateKey, certChain ) );
    delete storage;
    CleanupStack::PopAndDestroy( i + 1 ); // certs & dir
    CleanupStack::PopAndDestroy( 3 ); // privateKey, certChain, buffers
    LOG( _L( "CRoapStorageServer::ImportKeysL done" ) );
    __UHEAP_MARKEND;
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================
// -----------------------------------------------------------------------------
// Function StartupRoapStorage().
// This function starts the actual Roap Storage
// the cleanup stack and active scheduler.
// Returns: TInt: Symbian OS error code.
// -----------------------------------------------------------------------------
//

TInt StartupRoapStorage( TAny* ) 
    {    
    TInt error = KErrNone;
    CTrapCleanup* trap = CTrapCleanup::New();
    __ASSERT_ALWAYS( trap, User::Invariant() );
    
    CActiveScheduler* scheduler = new CActiveScheduler();
    __ASSERT_ALWAYS( scheduler, User::Invariant() );
    
    CActiveScheduler::Install( scheduler );
    RSemaphore clientSem;
    __ASSERT_ALWAYS( clientSem.OpenGlobal( KDRMEngCommonSemaphore ) == 0, User::Invariant() );
    
    error = StartRoapServer( clientSem );
    
    if ( error ) {
        // Server creation failed. Release the semaphore.
        // In case of successful startup, CRoapStorageServer
        // releases the semaphore.
        clientSem.Signal();
        clientSem.Close();
        }
    
    delete scheduler; 
    scheduler = NULL;
    
    delete trap;
    trap = NULL;
    
    // __ASSERT_ALWAYS( !error, User::Invariant() );
    
    return KErrNone;
    }

//  End of File