/*
* Copyright (c) 2002-2010 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: Presence handler.
*
*/
#include <ximperrors.hrh>
#include <ximpcontext.h>
#include <presenceinfo.h> //MximpPresenceInfo
#include <presenceinfofilter.h> //info filtter
#include <presenceinfofield.h> //MximpPresenceInfoField
#include <ximpobjectfactory.h>
#include <presenceobjectfactory.h>
#include <servicepresenceinfo.h> //MximpServicePresenceInfo
#include <presenceinfofieldvalueenum.h> //MximpPresenceInfoFieldValueEnum
#include <presenceinfofieldcollection.h> //MximpPresenceInfoFieldCollection
#include <presenceinfofieldvaluetext.h> //MximpPresenceInfoFieldValueText
#include <personpresenceinfo.h> // MximpPersonPresenceInfo
#include <presencepublishing.h>//MPresencePublishing
#include <ximpfeatureinfo.h>
#include <presencefeatures.h>
#include <ximpidentity.h> //for MXIMPIdentity
#include <presentitygroups.h>
#include <ximprequestcompleteevent.h>
#include <ximpcontextstateevent.h>
#include <ownpresenceevent.h>
#include <ximpclient.h>
#include <ximpcontext.h>
#include <ximpstatus.h>
#include <pressettingsapi.h> //presence settings
#include <xdmsettingsapi.h>
#include <cvimpstsettingsstore.h>
#include "scppresencehandler.h"
#include "scpsubservice.h"
#include "scpservicestorage.h"
#include "scplogger.h"
#include "scputility.h"
#include "scpservice.h"
#include "scpprofilehandler.h"
#include "scpsettinghandler.h"
#include "scppresencehandlerrequest.h"
const TInt KXdmDmMaxIntLength = 10; // max length of 32bit integer
const TInt KMaxPresenceEnableCount = 5;
const TInt KCustomMessageMaxLength = 75;
const TInt KBufSize255 = 255;
// -----------------------------------------------------------------------------
// CScpPresenceHandler::NewL
// -----------------------------------------------------------------------------
//
CScpPresenceHandler* CScpPresenceHandler::NewL( CScpSubService& aSubService )
{
SCPLOGSTRING( "CScpPresenceHandler::NewL" );
CScpPresenceHandler* self = new ( ELeave ) CScpPresenceHandler( aSubService );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::CCScpPresenceHandler
// -----------------------------------------------------------------------------
//
CScpPresenceHandler::CScpPresenceHandler( CScpSubService& aSubService ) :
CScpServiceHandlerBase( aSubService ),
iPresenceState( ENoBind ),
iDisableAfterXimpRequestsCompleted( EFalse )
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::CScpPresenceHandler", this );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::ConstructL
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::ConstructL()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::ConstructL", this );
BaseConstructL();
GetPresencePropertyIdL( ESubPropertyPresenceSettingsId, iPresenceSettingsId );
iPresClient = MXIMPClient::NewClientL();
SCPLOGSTRING2( "CScpPresenceHandler::ConstructL, iPresClient [0x%x]", iPresClient );
if ( iPresClient )
{
// Set presence handler as observer of Voip subservice
CScpSubService* voipSubService = GetVoipSubService();
if ( voipSubService )
{
voipSubService->SetSubServiceObserver( this );
}
MXIMPContext* tmp = iPresClient->NewPresenceContextLC();
iFeature = MPresenceFeatures::NewL( tmp );
RArray<TInt32> eventFilter;
CleanupClosePushL( eventFilter );
eventFilter.Append( XIMP_IF_ID_REQUEST_COMPLETE_EVENT );
eventFilter.Append( XIMP_IF_ID_CONTEXT_STATE_EVENT );
TArray<TInt32> eventFilterArray = eventFilter.Array();
tmp->RegisterObserverL( *this, &eventFilterArray );
CleanupStack::PopAndDestroy( &eventFilter );
CleanupStack::Pop(); // tmp
iPresenceCtx = tmp;
tmp = NULL;
}
else
{
User::Leave( KErrGeneral );
}
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::~CScpPresenceHandler
// -----------------------------------------------------------------------------
//
CScpPresenceHandler::~CScpPresenceHandler()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::~CScpPresenceHandler", this );
CancelDisableTimer();
iReqIdArray.Close();
delete iFeature;
delete iPresenceCtx;
// Set observer of Voip subservice to NULL
CScpSubService* voipSubService = GetVoipSubService();
if ( voipSubService )
{
voipSubService->SetSubServiceObserver( NULL );
}
delete iPresClient;
}
// ====================== From CScpServiceHandlerBase ==========================
// -----------------------------------------------------------------------------
// CScpPresenceHandler::EnableSubServiceL
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::EnableSubServiceL()
{
SCPLOGSTRING4( "CScpPresenceHandler[0x%x]::EnableSubServiceL: 0x%x type: %i",
this, &iSubService, iSubService.SubServiceType() );
__ASSERT_DEBUG( iSubService.SubServiceType() == ECCHPresenceSub,
User::Panic( KNullDesC, KErrGeneral ) );
CScpServiceHandlerBase::RegisterProfileL();
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::DisableSubService
// -----------------------------------------------------------------------------
//
TInt CScpPresenceHandler::DisableSubService()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::DisableSubService", this );
__ASSERT_DEBUG( iSubService.SubServiceType() == ECCHPresenceSub,
User::Panic( KNullDesC, KErrGeneral ) );
TInt result = KErrNone;
// Publish offline and unbind presence context
TRAP( result, HandleDeregistrationL( ETrue ) );
if ( KErrNone == result )
{
// Deregister if still connecting
if ( iSubService.State() == ECCHConnecting )
{
DeregisterNow();
}
else
{
StartForcedDisableTimer( CScpPresenceHandler::ForcePresenceServiceDisable );
}
}
else
{
// Wait for XIMP request to be completed and handle
// de-registration after that or after force disable timer expires
if ( iReqIdArray.Count() )
{
iDisableAfterXimpRequestsCompleted = ETrue;
StartForcedDisableTimer( CScpPresenceHandler::ForcePresenceServiceDisable );
}
else
{
DeregisterNow();
}
}
return result;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::SubServiceType
// -----------------------------------------------------------------------------
//
TCCHSubserviceType CScpPresenceHandler::SubServiceType() const
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::SubServiceType", this );
return ECCHPresenceSub;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleSipConnectionEvent
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleSipConnectionEvent( const TUint32 aProfileId,
TScpConnectionEvent aEvent )
{
SCPLOGSTRING4( "CScpPresenceHandler[0x%x]::HandleSipConnectionEvent id: %d event: %d",
this, aProfileId, aEvent );
if ( iSubService.SipProfileId() == aProfileId &&
iSubService.EnableRequestedState() != CScpSubService::EScpNoRequest )
{
//if network lost, unbind context
if ( EScpNetworkLost == aEvent )
{
SCPLOGSTRING( "CScpPresenceHandler - EScpNetworkLost -> unbind" );
TRAPD( err, HandleDeregistrationL( EFalse ) );
if ( KErrNotReady == err )
{
SCPLOGSTRING( "CScpPresenceHandler - EScpNetworkLost -> note ready: unbind" );
TRAP_IGNORE( ServerUnBindL() );
}
}
if ( EScpRoaming == aEvent )
{
SCPLOGSTRING( "CScpPresenceHandler - EScpRoaming -> unbind" );
TRAP_IGNORE( ServerUnBindL() );
}
//if registered, time to bind context
if ( EScpRegistered == aEvent &&
CScpSubService::EScpEnabled == iSubService.EnableRequestedState() )
{
SCPLOGSTRING( "CScpPresenceHandler - EScpRegistered -> update iap and bind" );
// update xmd settings
TRAPD( err, UpdateXdmSettingsL() );
if ( KErrNone == err )
{
// Subscribe
TRAP( err, ServerBindL() );
iRebind = EFalse;
if( KErrNone == err )
{
// Still connecting the service
aEvent = EScpNetworkFound;
}
else
{
SCPLOGSTRING2( "ServerBindL failed: %d", err );
aEvent = EScpRegistrationPending;
if ( KErrAlreadyExists == err )
{
// Ximp does not set request to queue, so we have to do rebind later
SCPLOGSTRING( "CScpPresenceHandler - rebind later" );
iRebind = ETrue;
}
}
}
else
{
SCPLOGSTRING2( "UpdateXdmSettingsL: %d", err );
aEvent = EScpRegistrationFailed;
}
}
else if ( EScpDeregistered == aEvent &&
iSubService.EnableRequestedState() == CScpSubService::EScpDisabled ||
iSubService.EnableRequestedState() == CScpSubService::EScpRefreshed )
{
if ( EScpRegistered != aEvent && ECCHDisconnecting != iSubService.State() )
{
CancelDisableTimer();
}
// If this flag is still true, it could be that presence server
// has not given answer -> ximp requests cannot be completed.
// But still have to unbind from ximp context
if ( iDisableAfterXimpRequestsCompleted )
{
TRAP_IGNORE( ServerUnBindL() );
}
// When SIP is deregistered, change presence state to no bind
iPresenceState = ENoBind;
}
iSubService.HandleConnectionEvent( aEvent );
}
SCPLOGSTRING( "CScpPresenceHandler::HandleSipConnectionEvent OUT" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleSipConnectionEvent
// -----------------------------------------------------------------------------
//
TBool CScpPresenceHandler::IsSipProfileAllowedToStartAlr()
{
return EFalse;
}
// ======================= From MXIMPContextObserver ===========================
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandlePresenceContextEvent
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandlePresenceContextEvent(
const MXIMPContext& /*aContext*/,
const MXIMPBase& aEvent )
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::HandlePresenceContextEvent", this );
const TInt32 eventType = aEvent.GetInterfaceId();
switch ( eventType )
{
case MXIMPContextStateEvent::KInterfaceId:
{
HandleContextStateEvent( aEvent );
break;
}
case MXIMPRequestCompleteEvent::KInterfaceId:
{
HandleRequestCompleteEvent( aEvent );
break;
}
default:
{
break;
}
}
SCPLOGSTRING( "CScpPresenceHandler::HandlePresenceContextEvent end" );
}
// ===================== From MScpSubServiceObserver ===========================
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleSubServiceChange
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleSubServiceChange( TCCHSubserviceState aState, TInt aError )
{
SCPLOGSTRING4( "CScpPresenceHandler::HandleSubServiceChange presence subservice state: %d, aState: %d, aError: %d",
iSubService.State(), aState, aError );
if ( iSubService.State() == ECCHEnabled && ( aError == KCCHErrorBandwidthInsufficient || aError == KErrNone ) )
{
if( aState == ECCHEnabled && aError == KErrNone )
{
if ( EPresenceOffline == iPresenceState )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleSubServiceChange PublishOnline" );
TRAP_IGNORE( PublishPresenceL( ETrue ) );
}
}
else
{
if ( EPresenceOnline == iPresenceState && aState != ECCHConnecting )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleSubServiceChange PublishOffline" );
// Unsubscribe from the list first
TRAP_IGNORE( UnsubscribePresentityGroupL() );
TRAP_IGNORE( PublishPresenceL( EFalse ) );
}
}
}
}
// ========================= Other member funcions =============================
// -----------------------------------------------------------------------------
// CScpPresenceHandler::GetVoipSubService
// -----------------------------------------------------------------------------
//
CScpSubService* CScpPresenceHandler::GetVoipSubService()
{
CScpSubService* voipSubService = NULL;
CScpServiceStorage& serviceStorage = iSubService.ServiceStorage();
CScpService* service = serviceStorage.GetServiceByServiceId( iSubService.SubServiceId() );
if ( service )
{
voipSubService = service->GetSubServiceByType( ECCHVoIPSub );
}
return voipSubService;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::DeregisterNow
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::DeregisterNow()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::DeregisterNow",
this );
CancelDisableTimer();
iReqIdArray.Reset();
iPresenceState = ENoBind;
// Check if disable was not requested
if ( iSubService.EnableRequestedState() == CScpSubService::EScpEnabled )
{
// Check the last ximp error
if ( KErrNoMemory == iLastXimpError &&
KMaxPresenceEnableCount < iSubService.EnableCounter() )
{
// No memory means 401 Unauthorized, we are trying to enable
// KMaxPresenceEnableCount times -> no more, this is truly
// autentication failed.
iSubService.HandleConnectionEvent( EScpAuthenticationFailed );
}
else
{
iSubService.HandleConnectionEvent( EScpDeregistered );
}
}
else
{
DeregisterProfile();
}
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::ForcePresenceServiceDisable
// -----------------------------------------------------------------------------
//
TInt CScpPresenceHandler::ForcePresenceServiceDisable( TAny* aSelf )
{
SCPLOGSTRING( "CScpPresenceHandler::ForcePresenceServiceDisable" );
CScpPresenceHandler* self = static_cast<CScpPresenceHandler*>( aSelf );
self->DeregisterNow();
return 1;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::UpdateXdmSettingsL
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::UpdateXdmSettingsL()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::UpdateXdmSettingsL", this );
// Get IAP id of sip profile
CScpProfileHandler& profileHandler = iSubService.ProfileHandler();
CScpSipConnection* sipConnection = profileHandler.GetSipConnection( iSubService.SipProfileId() );
if ( !sipConnection )
{
User::Leave( KErrNotFound );
}
TUint32 apId = 0;
User::LeaveIfError( sipConnection->GetIap( apId ) );
SCPLOGSTRING2( "CScpPresenceHandler::UpdateXdmSettingsL apId is %d", apId );
TPresSettingsSet mySet;
User::LeaveIfError( PresSettingsApi::SettingsSetL( iPresenceSettingsId, mySet ));
// set iap id to xdm settings
HBufC* idBuf = HBufC::NewLC( KXdmDmMaxIntLength );
TPtr ptrBuf = idBuf->Des();
ptrBuf.AppendNum( apId );
TXdmSettingsApi::UpdatePropertyL( mySet.iXDMSetting, *idBuf, EXdmPropToNapId );
CleanupStack::PopAndDestroy( idBuf );
SCPLOGSTRING( "CScpPresenceHandler::UpdateXdmSettingsL status online end" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::GetPresencePropertyIdL
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::GetPresencePropertyIdL( TServicePropertyName aProperty,
TInt& aValue ) const
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::GetPresenceSettingsId", this );
CScpServiceStorage& serviceStorage = iSubService.ServiceStorage();
CScpSettingHandler& settingHandler = serviceStorage.SettingsHandler();
settingHandler.GetSPSettingsIntPropertyL( iSubService.SubServiceId(),
aProperty,
aValue );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::PublishPresenceL
// Publishes presence according to given parameter.
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::PublishPresenceL( TBool aPublishOnline )
{
SCPLOGSTRING3( "CScpPresenceHandler[0x%x]::PublishPresenceL, aPublishOnline = %d",
this, aPublishOnline );
// Get the management interface
MPresencePublishing* presPub = &( iFeature->PresencePublishing() );
// publish own presence in here
MPresenceInfo* info = CreateInfoLC( aPublishOnline );
TScpReqId reqId;
if ( aPublishOnline )
{
reqId.SetType( EPublishOnlineReq );
iPresenceState = EPublishing;
}
else
{
reqId.SetType( EPublishOfflineReq );
iPresenceState = EPresenceOffline;
}
reqId.SetId( presPub->PublishOwnPresenceL( *info ) );
iReqIdArray.Append( reqId );
CleanupStack::PopAndDestroy( 1 );
SCPLOGSTRING( "CScpPresenceHandler::PublishPresenceL end" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::ServerBindL
// Binds the presence context
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::ServerBindL()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::ServerBindL", this );
SCPLOGSTRING2( "CScpPresenceHandler::ServerBindL -> bind service: %d",
iSubService.SubServiceId() );
//Bind context to desired presence service
TInt propertyId = 0;
GetPresencePropertyIdL( EPropertyPCSPluginId, propertyId );
TUid protocolUid = TUid::Uid( propertyId );
TScpReqId reqId;
reqId.SetType( EBindReq );
reqId.SetId( iPresenceCtx->BindToL( protocolUid, iSubService.SubServiceId() ) );
iReqIdArray.Append( reqId );
iPresenceState = EBinding;
SCPLOGSTRING( "CScpPresenceHandler::ServerBindL end" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::ServerUnBindL
// Unbinds the presence context
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::ServerUnBindL()
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::ServerUnBindL", this );
TScpReqId reqId;
reqId.SetType( EUnBindReq );
reqId.SetId( iPresenceCtx->UnbindL() );
iReqIdArray.Append( reqId );
iPresenceState = EUnBinding;
SCPLOGSTRING( "CScpPresenceHandler::ServerUnBindL end" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleDeregistrationL
// Handles the deregistration of presence.
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleDeregistrationL( TBool aDoStopPublish )
{
SCPLOGSTRING4( "CScpPresenceHandler[0x%x]::HandleDeregistrationL, aDoStopPublish: %d, iPresenceState: %d",
this, aDoStopPublish, iPresenceState );
if ( EPresenceOnline == iPresenceState
&& aDoStopPublish &&
iSubService.LastReportedError() == KErrNone )
{
// Get the management interface
MPresencePublishing* presPub = &( iFeature->PresencePublishing() );
// publish own presence in here
MPresenceInfo* info = CreateInfoLC( EFalse );
TScpReqId reqId;
// After publishing offline, we need to unbind because we are
// deregistering, so offline request id needs to be saved and handled
reqId.SetType( EPublishOfflineReq );
reqId.SetId( presPub->PublishOwnPresenceL( *info ) );
iPresenceState = EPresenceOffline;
iReqIdArray.Append( reqId );
CleanupStack::PopAndDestroy( 1 ); // info
}
else
{
//unbind if there are no other requests going on.
//in case of ongoing unprocessed requests,
//reset array (further events ignored) and
//leave here to deregister properly
if ( iReqIdArray.Count() > 0 )
{
User::Leave( KErrNotReady );
}
else
{
ServerUnBindL();
}
}
SCPLOGSTRING( "CScpPresenceHandler::HandleDeregistrationL end" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::CreateInfoLC
// Creates presence info item
// -----------------------------------------------------------------------------
//
MPresenceInfo* CScpPresenceHandler::CreateInfoLC( TBool aState )
{
SCPLOGSTRING2( "CScpPresenceHandler[0x%x]::CreateInfoLC", this );
MPresenceInfo* info =
iFeature->PresenceObjectFactory().NewPresenceInfoLC();
// fill service info
MServicePresenceInfo* srvInfo =
iFeature->PresenceObjectFactory().NewServicePresenceInfoLC();
srvInfo->SetServiceTypeL(
NPresenceInfo::NServiceType::KVoip ); // voip
MPresenceInfoField* infoField =
iFeature->PresenceObjectFactory().NewInfoFieldLC();
MPresenceInfoFieldValueEnum* enumField =
iFeature->PresenceObjectFactory().NewEnumInfoFieldLC();
// Set the textfield's value according to aState
if ( aState )
{
enumField->SetValueL( NPresenceInfo::EAvailable );
}
else
{
enumField->SetValueL( NPresenceInfo::ENotAvailable );
}
infoField->SetFieldTypeL(
NPresenceInfo::NFieldType::KAvailabilityEnum ); // "availability"
infoField->SetFieldValue( enumField );
CleanupStack::Pop(); // enumField
srvInfo->Fields().AddOrReplaceFieldL( infoField );
CleanupStack::Pop(); // infoField
info->AddServicePresenceL( srvInfo );
CleanupStack::Pop(); // srvInfo
// fill person info
MPersonPresenceInfo* persInfo =
iFeature->PresenceObjectFactory().NewPersonPresenceInfoLC();
MPresenceInfoField* infoField2 =
iFeature->PresenceObjectFactory().NewInfoFieldLC();
MPresenceInfoFieldValueEnum* enumField2 =
iFeature->PresenceObjectFactory().NewEnumInfoFieldLC();
TInt availabilityEnum(0);
RBuf customMessage;
CleanupClosePushL( customMessage );
customMessage.Create( KCustomMessageMaxLength );
GetStoredPresenceValuesL( availabilityEnum, customMessage );
switch( availabilityEnum )
{
case NPresenceInfo::EAvailable:
{
enumField2->SetValueL( NPresenceInfo::EAvailable );
break;
}
case NPresenceInfo::ENotAvailable:
{
enumField2->SetValueL( NPresenceInfo::ENotAvailable );
break;
}
case NPresenceInfo::EBusy:
{
enumField2->SetValueL( NPresenceInfo::EBusy );
break;
}
case NPresenceInfo::EDoNotDisturb:
{
enumField2->SetValueL( NPresenceInfo::EDoNotDisturb );
break;
}
case NPresenceInfo::EAway:
{
enumField2->SetValueL( NPresenceInfo::EAway );
break;
}
// if presence availability is not stored
default:
{
if ( aState )
{
enumField2->SetValueL( NPresenceInfo::EAvailable );
}
else
{
enumField2->SetValueL( NPresenceInfo::ENotAvailable );
}
break;
}
}
// set custom message if available
if( customMessage.Length() )
{
MPresenceInfoField* customMessageinfoField =
iFeature->PresenceObjectFactory().NewInfoFieldLC();
MPresenceInfoFieldValueText* textField =
iFeature->PresenceObjectFactory().NewTextInfoFieldLC();
textField->SetTextValueL( customMessage );
customMessageinfoField->SetFieldTypeL(
NPresenceInfo::NFieldType::KStatusMessage );
customMessageinfoField->SetFieldValue( textField );
CleanupStack::Pop(); //textField
persInfo->Fields().AddOrReplaceFieldL( customMessageinfoField );
CleanupStack::Pop(); //customMessageinfoField
}
CleanupStack::PopAndDestroy( &customMessage );
infoField2->SetFieldTypeL(
NPresenceInfo::NFieldType::KAvailabilityEnum );
infoField2->SetFieldValue( enumField2 );
CleanupStack::Pop(); // enumField2
persInfo->Fields().AddOrReplaceFieldL( infoField2 );
CleanupStack::Pop(); // infoField2
info->SetPersonPresenceL( persInfo );
CleanupStack::Pop(); // persInfo
return info;
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleContextStateEvent
// Handles the XIMP context state events
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleContextStateEvent( const MXIMPBase& aEvent )
{
const MXIMPContextStateEvent* event =
TXIMPGetInterface< const MXIMPContextStateEvent >::From( aEvent, MXIMPBase::EPanicIfUnknown );
MXIMPContextState::TState ctxState = event->ContextState().ContextState();
SCPLOGSTRING2( "CScpPresenceHandler: MXIMPContextStateEvent: %d", (TInt)ctxState );
const MXIMPStatus* status = event->StateChangeReason();
if ( status )
{
iLastXimpError = status->ResultCode();
}
SCPLOGSTRING2( "CScpPresenceHandler -> context ximp error: %d", iLastXimpError );
// Go through the reqid array to see, if unbind has been requested
TBool unBindRequested( EFalse );
for ( TInt i = 0; i < iReqIdArray.Count(); i++ )
{
if ( iReqIdArray[i].Type() == EUnBindReq )
{
unBindRequested = ETrue;
}
}
if ( ctxState == MXIMPContextState::EInactive &&
iReqIdArray.Count() > 0 &&
!unBindRequested )
{
//Unbind was not requested, but EInactive state event received => try forced unbind
TRAPD( binderr, HandleDeregistrationL( EFalse ) );
SCPLOGSTRING2( "CScpPresenceHandler::HandleContextStateEvent: Unbind err:%d", binderr );
if ( KErrNone != binderr )
{
DeregisterNow();
}
}
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleRequestCompleteEvent
// Handles the XIMP request complete events
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleRequestCompleteEvent( const MXIMPBase& aEvent )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleRequestCompleteEvent event MximpRequestCompleteEvent" );
const MXIMPRequestCompleteEvent* event =
TXIMPGetInterface< const MXIMPRequestCompleteEvent >::From( aEvent, MXIMPBase::EPanicIfUnknown );
const TXIMPRequestId& reqId = event->RequestId();
const MXIMPStatus& status = event->CompletionResult();
if ( &status )
{
iLastXimpError = status.ResultCode();
}
SCPLOGSTRING2( "CScpPresenceHandler -> request ximp error: %d", iLastXimpError );
if ( iLastXimpError == KXIMPErrServicRequestTimeouted )
{
iSubService.HandleConnectionEvent( EScpRegistrationFailed );
}
// Find the reqId from the reqid array and store it's type
TInt index( KErrNotFound );
TScpReqType reqType( EUnknownReq );
for ( TInt i = 0; i < iReqIdArray.Count(); i++ )
{
if ( iReqIdArray[i].ReqId() == reqId )
{
index = i;
reqType = iReqIdArray[i].Type();
}
}
if ( index != KErrNotFound )
{
iReqIdArray.Remove( index );
}
SCPLOGSTRING2( "CScpPresenceHandler -> request type: %d", reqType );
// Bind complete event
if ( ( reqType == EBindReq ) &&
( EBinding == iPresenceState ) &&
( iLastXimpError == KErrNone ) )
{
HandleBindCompleteEvent();
}
// Published online request complete
else if ( ( reqType == EPublishOnlineReq ) &&
( iLastXimpError == KErrNone ) )
{
TRAP_IGNORE( SubscribePresentityGroupL() );
iPresenceState = ESubscribing;
}
else if ( ( reqType == ESubscribeReq ) &&
( iLastXimpError == KErrNone ) )
{
// Set subservice enabled after subscribe is successfully done
iPresenceState = EPresenceOnline;
iSubService.HandleConnectionEvent( EScpRegistered );
}
// Published offline request complete
else if ( reqType == EPublishOfflineReq )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleRequestCompleteEvent status offline Unbind now" );
TRAPD( err, ServerUnBindL() );
// Deregistration ongoing, so if unbind fails, deregisterNow is called
if ( err )
{
DeregisterNow();
SCPLOGSTRING2( "CScpPresenceHandler::HandleRequestCompleteEvent status offline Unbind now end, err %d", err );
}
}
// Unbind request complete
else if ( reqType == EUnBindReq && EUnBinding == iPresenceState )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleRequestCompleteEvent status offline" );
// Do not send info to our client if roaming is ongoing
if ( !iSubService.IsRoaming() )
{
DeregisterNow();
}
// Inform SIP to start ALR migration
else
{
iSubService.ProfileHandler().StartAlrMigration( iSubService.SipProfileId() );
}
SCPLOGSTRING( "CScpPresenceHandler::HandleRequestCompleteEvent status offline end" );
}
if ( iRebind )
{
TRAPD( err, ServerBindL() );
iRebind = EFalse;
SCPLOGSTRING2( "CScpPresenceHandler - ServerBindL failed: %d", err );
if ( KErrAlreadyExists == err )
{
iRebind = ETrue;
}
}
if ( iDisableAfterXimpRequestsCompleted && !iReqIdArray.Count() )
{
iDisableAfterXimpRequestsCompleted = EFalse;
DeregisterNow();
}
SCPLOGSTRING( "CScpPresenceHandler::HandleRequestCompleteEvent OUT" );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::HandleBindCompleteEvent
// Handles the bind complete event
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::HandleBindCompleteEvent()
{
SCPLOGSTRING( "CScpPresenceHandler::HandleBindCompleteEvent" );
iPresenceState = EBindComplete;
TInt err( KErrNone );
CScpSubService* voipSubService = GetVoipSubService();
if ( voipSubService )
{
if ( voipSubService->State() == ECCHEnabled &&
voipSubService->LastReportedError() == KErrNone )
{
SCPLOGSTRING( "CScpPresenceHandler::HandleBindCompleteEvent PublishOnline");
TRAP( err, PublishPresenceL( ETrue ) );
}
else
{
SCPLOGSTRING( "CScpPresenceHandler::HandleBindCompleteEvent PublishOffline");
TRAP( err, PublishPresenceL( EFalse ) );
}
}
else
{
SCPLOGSTRING( "CScpPresenceHandler::HandleBindCompleteEvent PublishOffline, no VoIP");
TRAP( err, PublishPresenceL( EFalse ) );
err = KErrNotFound;
}
if ( err )
{
SCPLOGSTRING2( "CScpPresenceHandler::HandleBindCompleteEvent err %d", err );
}
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::SubscribePresentityGroupL
//
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::SubscribePresentityGroupL()
{
SCPLOGSTRING( "CScpPresenceHandler::SubscribePresentityGroupL subsribe buddies" );
MXIMPObjectFactory& objFactoryFromXIMP = iPresenceCtx->ObjectFactory();
//First we have to make identity
SCPLOGSTRING( "CScpPresenceHandler::SubscribePresentityGroupL create buddy list identity" );
MXIMPIdentity* groupIdentity = objFactoryFromXIMP.NewIdentityLC();
groupIdentity->SetIdentityL( _L("buddylist") ); // NEEDS TO BE DEFINED IN XIMP API
SCPLOGSTRING( "CScpPresenceHandler::SubscribePresentityGroupL subsribe group content" );
TScpReqId reqId;
reqId.SetType( ESubscribeReq );
reqId.SetId( iFeature->PresentityGroups().SubscribePresentityGroupContentL(
*groupIdentity ) );
SCPLOGSTRING( "CScpPresenceHandler::SubscribePresentityGroupL append req to array" );
iReqIdArray.Append( reqId );
SCPLOGSTRING( "CScpPresenceHandler::SubscribePresentityGroupL subsribe group content ok" );
CleanupStack::PopAndDestroy( 1 ); // groupIdentity
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::UnsubscribePresentityGroupL
//
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::UnsubscribePresentityGroupL()
{
MXIMPObjectFactory& objFactoryFromXIMP = iPresenceCtx->ObjectFactory();
//First we have to make identity
MXIMPIdentity* groupIdentity = objFactoryFromXIMP.NewIdentityLC();
groupIdentity->SetIdentityL( _L("buddylist") ); // NEEDS TO BE DEFINED IN XIMP API
TScpReqId reqId;
// Set type to Unknown, because we don't need to handle the
// request complete event
reqId.SetType( EUnknownReq );
reqId.SetId( iFeature->PresentityGroups().UnsubscribePresentityGroupContentL(
*groupIdentity ) );
iReqIdArray.Append( reqId );
CleanupStack::PopAndDestroy( 1 );
}
// -----------------------------------------------------------------------------
// CScpPresenceHandler::GetStoredPresenceValuesL
//
// -----------------------------------------------------------------------------
//
void CScpPresenceHandler::GetStoredPresenceValuesL( TInt& aAvailabilityEnum, RBuf& aCustomMessage )
{
MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC();
TInt serviceId = iSubService.SubServiceId();
RBuf8 documentId;
CleanupClosePushL( documentId );
documentId.CreateL( KBufSize255 );
TInt error = settings->GetL(
serviceId, EServicePresenceSessionIdentifier, documentId );
TInt i = documentId.Length();
TInt err1(0);
TInt err2(0);
if( documentId.Length() )
{
err1 = settings->GetL(
serviceId, EServicePresenceAvailablilityValue, aAvailabilityEnum );
err2 = settings->GetL(
serviceId, EServiceCustomStatusMessage, aCustomMessage );
// if other GetL fails -> clear both
if( err1 || err2 )
{
aAvailabilityEnum = KErrNotFound;
aCustomMessage.Zero();
}
}
else
{
aAvailabilityEnum = KErrNotFound;
}
CleanupStack::PopAndDestroy( &documentId );
CleanupStack::PopAndDestroy(); //settings
}
// End of File