diff -r 000000000000 -r a4daefaec16c voipplugins/sipconnectionprovider/src/scppresencehandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/voipplugins/sipconnectionprovider/src/scppresencehandler.cpp Mon Jan 18 20:12:36 2010 +0200 @@ -0,0 +1,1059 @@ +/* +* Copyright (c) 2002-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: Presence handler. +* +*/ +#include +#include +#include //MximpPresenceInfo +#include //info filtter +#include //MximpPresenceInfoField +#include +#include +#include //MximpServicePresenceInfo +#include //MximpPresenceInfoFieldValueEnum +#include //MximpPresenceInfoFieldCollection +#include //MximpPresenceInfoFieldValueText +#include // MximpPersonPresenceInfo +#include //MPresencePublishing +#include +#include +#include //for MXIMPIdentity +#include + +#include +#include +#include +#include +#include +#include +#include //presence settings +#include +#include + +#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 eventFilter; + CleanupClosePushL( eventFilter ); + + eventFilter.Append( XIMP_IF_ID_REQUEST_COMPLETE_EVENT ); + eventFilter.Append( XIMP_IF_ID_CONTEXT_STATE_EVENT ); + + TArray 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; + } + 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" ); + TRAP_IGNORE( HandleDeregistrationL( EFalse ) ); + } + + 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(); + } + // When SIP is deregistered, change presence state to no bind + iPresenceState = ENoBind; + } + iSubService.HandleConnectionEvent( aEvent ); + } + SCPLOGSTRING( "CScpPresenceHandler::HandleSipConnectionEvent OUT" ); + } + + +// ======================= 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(); + + 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( 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" ); + DeregisterNow(); + 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; + DisableSubService(); + } + + 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