/*
* Copyright (c) 2002-2005 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: Server connection handler.
*
*/
// INCLUDE FILES
#include <e32math.h>
#include <e32uid.h>
#include "PhCltTypes.h"
#include "RPhCltServer.h"
#include "PhCltClientServer.h"
// CONSTANTS
// Information of Phone Server Startup failure, used in panic call.
_LIT( PH_SRV_SU_FAILURE, "PhSrvStartUp" );
// The number of Phone Server startup attempts.
const TInt KPhCltNumberOfRetryAttempts = 4;
// The phase were the Phone Server failure happened.
// Useful in debug purposes if Phone Server startup fails.
enum
{
EPhSrvStartupFailurePhase1, // First phase
EPhSrvStartupFailurePhase2 // Second phase
};
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// RPhCltServer::RPhCltServer
// C++ constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
EXPORT_C RPhCltServer::RPhCltServer()
: RSessionBase()
{
}
// -----------------------------------------------------------------------------
// RPhCltServer::Version
//
// Returns version.
// -----------------------------------------------------------------------------
//
TVersion RPhCltServer::Version() const
{
return TVersion( KPhoneServerMajorVersionNumber,
KPhoneServerMinorVersionNumber,
KPhoneServerBuildVersionNumber );
}
// -----------------------------------------------------------------------------
// RPhCltServer::Connect
//
// Creates connection to the server. If server is not running,
// it is also launched.
// -----------------------------------------------------------------------------
//
EXPORT_C TInt RPhCltServer::Connect( TInt aMessageSlots )
{
TInt err = KErrGeneral;
TInt count = KPhCltNumberOfRetryAttempts;
FOREVER
{
err = CreateSession( PHONE_SERVER_NAME, Version(), aMessageSlots );
if ( err != KErrNotFound && err != KErrServerTerminated )
{
break;
}
// Need to restart server
if ( --count < 0 )
{
break;
}
err = StartServer();
if ( err != KErrNone && err != KErrAlreadyExists )
{
if ( err != KErrNotFound )
{
break;
}
Panic( EPhCltPanicServerUnexpectedServerNotFound );
}
}
return err;
}
// -----------------------------------------------------------------------------
// RPhCltServer::CreateAll
// -----------------------------------------------------------------------------
//
EXPORT_C void RPhCltServer::CreateAll( TRequestStatus& aStatus )
{
SendReceive(
EPhoneCreateAll,
TIpcArgs(),
aStatus );
}
// -----------------------------------------------------------------------------
// RPhCltServer::StartServer
//
// Launches the phone server, which is assumed to be not
// already running.
// -----------------------------------------------------------------------------
//
TInt RPhCltServer::StartServer()
{
// The uid of the DLL/EXE - used to identify the correct target
const TUidType KPhServerUidType(
KExecutableImageUid,
KSharedLibraryUid,
KPhCltServerUid );
//////////////////////////////////////////////////////////////////////////
// On MARM, the server is an exe, so it is run inside its own process.
// The server itself takes care of creating a thread and finalizing the
// construction of the server. We pass the signalling object via the
// command line.
//////////////////////////////////////////////////////////////////////////
RProcess serverUnitOfExecution;
TFileName pathName( KPhCltServerZDrive );
pathName.Append( KDC_PROGRAMS_DIR );
pathName.Append( KPhServerPathAndNameMARM );
pathName.ZeroTerminate();
TInt err = serverUnitOfExecution.Create(
pathName,
KNullDesC,
KPhServerUidType );
if ( err != KErrNone )
{
User::Panic( PH_SRV_SU_FAILURE, err );
}
serverUnitOfExecution.SetPriority( EPriorityHigh );
// Now wait for the server to start up, and also observe if the server
// thread dies for any reason.
TRequestStatus stat;
serverUnitOfExecution.Rendezvous( stat );
if ( stat != KRequestPending )
{
User::Panic( PH_SRV_SU_FAILURE, EPhSrvStartupFailurePhase1 );
serverUnitOfExecution.Kill( KErrAbort ); // abort startup
}
else
{
serverUnitOfExecution.Resume(); // logon ok
}
// wait for start or death
User::WaitForRequest( stat );
// we can't use the 'exit reason' if the server panicked as this
// is the panic 'reason' and may be '0' which cannot be distinguished
// from KErrNone
err = ( serverUnitOfExecution.ExitType() == EExitPanic )
? KErrGeneral : stat.Int();
serverUnitOfExecution.Close();
return err;
}
// -----------------------------------------------------------------------------
// RPhCltServer::Panic
//
// Panics the client thread
// -----------------------------------------------------------------------------
//
void RPhCltServer::Panic( TPhCltPanicTypes aPanic )
{
User::Panic( KPhClientPanicCategory, aPanic );
}
// End of File