diff -r 000000000000 -r c8caa15ef882 simpleengine/engine/src/simplewatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simpleengine/engine/src/simplewatcher.cpp Tue Feb 02 01:05:17 2010 +0200 @@ -0,0 +1,610 @@ +/* +* Copyright (c) 2006,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: Simple Engine +* +*/ + + + + +// INCLUDE FILES + +#include +#include + +// own simple +#include "msimpleconnection.h" +#include "simpleconnection.h" +#include "simplecommon.h" +#include "simpleenginerequest.h" +#include "msimpledocument.h" +#include "msimplefilterdocument.h" +#include "msimplewatcherobserver.h" +#include "msimplepresencelist.h" +#include "simplewatcher.h" +#include "simpleerrors.h" +#include "simplexmlfactory.h" + +#include "simplesipconnection.h" + +#ifdef _DEBUG +#include "simpledebugutils.h" +#endif + +const TInt KExpandSize = 512; + + +// ================= MEMBER FUNCTIONS ======================= +// + +// ---------------------------------------------------------- +// CSimpleWatcher::CSimpleWatcher +// ---------------------------------------------------------- +// +CSimpleWatcher::CSimpleWatcher( + MSimpleConnection& aConn, + MSimpleWatcherObserver& aObserver ) +: CSimpleClient( aConn ), + iObserver( aObserver ), + iResCount(0), iComplete( EFalse ), + iBuffer(NULL) + { + } + +// ---------------------------------------------------------- +// CSimpleWatcher::~CSimpleWatcher +// ---------------------------------------------------------- +// +CSimpleWatcher::~CSimpleWatcher() + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: Destructor this=%d" ), (TInt)this ); +#endif + delete iBuffer; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::ConstructL +// ---------------------------------------------------------- +// +void CSimpleWatcher::ConstructL() + { + BaseConstructL(); + iBuffer = CBufFlat::NewL(KExpandSize); + } + +// ---------------------------------------------------------- +// CSimpleWatcher::NewL +// ---------------------------------------------------------- +// +CSimpleWatcher* CSimpleWatcher::NewL( + MSimpleConnection& aConn, + MSimpleWatcherObserver& aObserver ) + { + CSimpleWatcher* self = new (ELeave) CSimpleWatcher( + aConn, aObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: NewL this=%d" ), (TInt)self ); +#endif + return self; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::Connection +// ---------------------------------------------------------- +// +const MSimpleConnection& CSimpleWatcher::Connection() + { + return iConn; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::SIPStatus +// ---------------------------------------------------------- +// +TUint CSimpleWatcher::SIPStatus() + { + return DoSIPStatus(); + } + +// ---------------------------------------------------------- +// CSimpleWatcher::SIPRetryAfter +// ---------------------------------------------------------- +// +TUint CSimpleWatcher::SIPRetryAfter() + { + return DoRetryAfter(); + } + +// ---------------------------------------------------------- +// CSimpleWatcher::SipSubscriptionState +// ---------------------------------------------------------- +// +MSimpleWatcher::TSimpleSipSubscriptionState CSimpleWatcher::SipSubscriptionState() + { + MSimpleWatcher::TSimpleSipSubscriptionState retVal = ESimpleStateNone; + + // get the old request + CSimpleEngineRequest* req = SearchRequests( iSubsId ); + if ( req ) + { + CSimpleConnection* conn = STATIC_CAST( CSimpleConnection*, &iConn); //lint !e826 + CSimpleSipConnection* engine = conn->Connection(); + MSimpleEngineRequest::TSimpleSipSubscriptionState intVal = engine->SipSubscriptionState( *req ); + switch ( intVal ) + { + case MSimpleEngineRequest::ESimpleStateNone: + retVal = MSimpleWatcher::ESimpleStateNone; + break; + case MSimpleEngineRequest::ESimpleStatePending: + retVal = MSimpleWatcher::ESimpleStatePending; + break; + case MSimpleEngineRequest::ESimpleStateActive: + retVal = MSimpleWatcher::ESimpleStateActive; + break; + case MSimpleEngineRequest::ESimpleStateTerminated: + default: + retVal = MSimpleWatcher::ESimpleStateTerminated; + break; + } + } + return retVal; + } + + +// ---------------------------------------------------------- +// CSimpleWatcher::Close +// ---------------------------------------------------------- +// +void CSimpleWatcher::Close( ) + { + delete this; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::NewRequestL +// ---------------------------------------------------------- +// +void CSimpleWatcher::NewRequestL( MSimpleEngineRequest& aReq ) + { + TPtrC8 content = aReq.ResponseData(); + TPtrC8 contType = aReq.ResponseContentType(); + TPtrC8 p8; + p8.Set( KSimpleDocumentType ); + TInt mySize = p8.Length(); + p8.Set( KSimpleMultipartType ); + TInt mySize2 = p8.Length(); + if (!contType.Left(mySize).CompareF(KSimpleDocumentType)) + { + MSimpleDocument* d = TSimpleXmlFactory::NewDocumentL( content ); + CleanupClosePushL( *d ); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: call WatcherNotificationL")); +#endif + iObserver.WatcherNotificationL( *d ); + CleanupStack::PopAndDestroy( d ); + } + else if ( !(contType.Left(mySize2).CompareF( KSimpleMultipartType ))) + { + // Detect the difference between multipart/related cases + // application/pidf+xml and application/rlmi+xml + if ( contType.FindF( KSimpleDocumentType ) > 0 ) + { + // Multipart for a single presentity having a direct content. + MSimpleDocument* d = TSimpleXmlFactory::NewDocumentInMultiPartL( + content, aReq.ResponseBoundary(), aReq.ResponseStart() ); + CleanupClosePushL( *d ); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: call WatcherNotificationL (content)")); +#endif + iObserver.WatcherNotificationL( *d ); + CleanupStack::PopAndDestroy( d ); + } + else + { + // Multipart for a presence list. + MSimplePresenceList* l = TSimpleXmlFactory::NewPresenceListL( + content, aReq.ResponseBoundary(), aReq.ResponseStart() ); + CleanupClosePushL( *l ); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: call WatcherListNotificationL")); +#endif + iObserver.WatcherListNotificationL( *l ); + CleanupStack::PopAndDestroy( l ); + } + } + else + { + // Unsupported content type, ignore it. + } + } + +// ---------------------------------------------------------- +// CSimpleWatcher::Complete +// ---------------------------------------------------------- +// +void CSimpleWatcher::Complete( + TInt aOpId, TInt aStatus, MSimpleEngineRequest& aReq ) + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: Complete opid=%d status=%d" ), + aOpId, aStatus ); +#endif + + // FUNCTIONALITY + // Get + // - SIP ok + terminated -> WatcherReqCompleteL(ok) + WatcherNotificationL(terminated) + // - terminated + SIP ok -> WatcherNotificationL(terminated) + WatcherReqCompleteL(ok) + // + // Stop + // - terminated + SIP ok -> WatcherReqCompleteL(ok) + // - SIP ok + terminated -> WatcherReqCompleteL(ok) + // + // Subscribe + // - SIP error -> WatcherReqCompleteL(error) + // - SIP ok + terminated -> + // WatcherReqCompleteL(ok) + WatcherNotificationL(terminated) + WatcherTerminated() + // - SIP ok + active + terminated -> + // WatcherReqCompleteL(ok) + WatcherNotificationL(active) + + // WatcherNotificationL(terminated) + WatcherTErminated + // - active + SIP ok + terminated -> + // WatcherNotificationL(active) + WatcherReqCompleteL(ok) + + // WatcherNotificationL(terminated) + WatcherTerminated + // + + TBool completeNow( EFalse ); + MSimpleEngineRequest::TSimpleRequest orig = aReq.RequestType(); + + if ( orig == MSimpleEngineRequest::EDestroyStart ) + { + // It's time to delete the request of delayed deletion from both DLLs. + // Delete immediately from another DLL. + aReq.ModifyType( MSimpleEngineRequest::EDestroy ); + TRAP_IGNORE( SendReqL( aReq )); + // Delete from this DLL, + aReq.Destroy(); + return; + } + + GetSIPStatus( aOpId ); + + // Reset data buffer + iBuffer->Reset(); + + // Set the member to point to stack variable + TBool destroyed( EFalse ); + iDestroyedPtr = &destroyed; + + MSimpleEngineRequest::TSimpleSIPResponse respMet = aReq.ResponseMethod(); + + // Convert KSimpleErrPending to OK when needed + if ( aStatus == KSimpleErrPending ) + { + aStatus = KErrNone; + } + + // Handle SIP notification first + if ( respMet == MSimpleEngineRequest::ENotify ) + { + // This is true in notifications. Ignore some responses. + if ( aStatus == KErrCompletion ) + { + iResCount++; + } + if ( orig != MSimpleEngineRequest::ESubscribeStop ) + { + TRAP_IGNORE( NewRequestL( aReq ) ); + // Check whether an application has called destructor in callback method. + // Destructor will handle deletion of all the open requests. + if ( destroyed ) + { + return; + } + } + else if ( iResCount > 1 ) + { + // Stop request is not completed until ok + Notify(terminated) received. + // Error completes the stop reqest without Notification. + completeNow = ETrue; + if ( DoCallReqComplete( aOpId, KErrNone )) + { + return; + } + } + } + else + { + // SIP Status response or client originated cancellation + iResCount++; + if ( aStatus != KErrNone ) + { + iResCount++; + if ( orig == MSimpleEngineRequest::ESubscribeStop ) + { + // Any response to stop subscribe is ok. + aStatus = KErrNone; + } + } + + if ( !iComplete && + ( orig != MSimpleEngineRequest::ESubscribeStop || + orig == MSimpleEngineRequest::ESubscribeStop && iResCount > 1 ) ) + { + // Stop request is not completed until ok + Notify(terminated) received. + // Error completes the stop reqest without Notification. + completeNow = ETrue; + if ( DoCallReqComplete( aOpId, aStatus )) + { + return; + } + } + } + + // Delete request when not needed + if ( iResCount > 1 ) + { + iRequest = MSimpleEngineRequest::ENone; + iComplete = EFalse; + TInt reason = ResponseReason( aReq ); + // Delete corresponding request from another DLL with delay. This decreases + // the counter of active subscriptions there. + aReq.ModifyType( MSimpleEngineRequest::EDestroyStart ); + TRAP_IGNORE( SendReqL( aReq )); + // call WatcherTerminatedL when needed, i.e. no Stop or Get + if ( orig != MSimpleEngineRequest::ESubscribeStop && + orig != MSimpleEngineRequest::ESubscribeGet && + !completeNow ) + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: call WatcherTerminatedL opid=%d"), + aOpId ); +#endif + TRAP_IGNORE( iObserver.WatcherTerminatedL( aOpId, reason )); + // Check whether an application has called destructor in callback method. + // Destructor of CSimpleClient base class will handle deletion of + // all the open requests. + if ( destroyed ) + { + return; + } + } + // delete request from this DLL later + } + + iDestroyedPtr = NULL; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::SubscribeL +// ---------------------------------------------------------- +// +TInt CSimpleWatcher::SubscribeL( + const TDesC8& aURI, + MSimpleFilterDocument* aFilter, + TBool aRefresh, + TBool aAnonymous ) + { + + if ( iRequest != MSimpleEngineRequest::ENone ) + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: SubscribeL IN-USE **" ) ); +#endif + User::Leave( KErrInUse ); + } + + IncreaseOpId(); + +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: SubscribeL opid=%d" ), iOpId ); +#endif + + CSimpleEngineRequest* req = CSimpleEngineRequest::NewL( + *this, MSimpleEngineRequest::ESubscribe, iOpId ); + CleanupStack::PushL( req ); + req->SetRemoteURIL( aURI ); + req->SetRefresh( aRefresh ); + if ( aAnonymous ) + { + req->SetAux( 1 ); + } + + // handle optional filter document + if ( aFilter ) + { + StreamDocumentL( *req, *aFilter ); + } + + SendReqL( *req ); + iRequestList.AddLast( *req ); + CleanupStack::Pop( req ); + + iRequest = MSimpleEngineRequest::ESubscribe; + iResCount = 0; + iSubsId = iOpId; + + return iOpId; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::SubscribeListL +// ---------------------------------------------------------- +// +TInt CSimpleWatcher::SubscribeListL( + const TDesC8& aURI, + MSimpleFilterDocument* aFilter, + TBool aRefresh, + TBool aAnonymous ) + { + if ( iRequest != MSimpleEngineRequest::ENone ) + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: SubscribeListL IN-USE **" ) ); +#endif + User::Leave( KErrInUse ); + } + + IncreaseOpId(); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: SubscribeListL opid=%d" ), iOpId); +#endif + + CSimpleEngineRequest* req = CSimpleEngineRequest::NewL( + *this, MSimpleEngineRequest::ESubscribeLista, iOpId ); + CleanupStack::PushL( req ); + req->SetRemoteURIL( aURI ); + req->SetRefresh( aRefresh ); + if ( aAnonymous ) + { + req->SetAux( 1 ); + } + + // handle optional filter document + if ( aFilter ) + { + StreamDocumentL( *req, *aFilter ); + } + + SendReqL( *req ); + iRequestList.AddLast( *req ); + CleanupStack::Pop( req ); + + iRequest = MSimpleEngineRequest::ESubscribeLista; + iResCount = 0; + iSubsId = iOpId; + + return iOpId; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::GetPresenceL +// ---------------------------------------------------------- +// +TInt CSimpleWatcher::GetPresenceL( + const TDesC8& aURI, + MSimpleFilterDocument* aFilter, + TBool aAnonymous ) + { + if ( iRequest != MSimpleEngineRequest::ENone ) + { +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: GetPresenceL IN-USE **" ) ); +#endif + User::Leave( KErrInUse ); + } + + IncreaseOpId(); +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: GetPresenceL opid=%d" ), iOpId ); +#endif + + CSimpleEngineRequest* req = CSimpleEngineRequest::NewL( + *this, MSimpleEngineRequest::ESubscribeGet, iOpId ); + CleanupStack::PushL( req ); + req->SetRemoteURIL( aURI ); + if ( aAnonymous ) + { + req->SetAux( 1 ); + } + + // handle optional filter document + if ( aFilter ) + { + StreamDocumentL( *req, *aFilter ); + } + + SendReqL( *req ); + iRequestList.AddLast( *req ); + CleanupStack::Pop( req ); + + iRequest = MSimpleEngineRequest::ESubscribeGet; + iResCount = 0; + + return iOpId; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::UnsubscribeL +// ---------------------------------------------------------- +// +TInt CSimpleWatcher::UnsubscribeL( ) + { + +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: UnsubscribeL opid=%d" ), iSubsId); +#endif + // use the old opid and request + CSimpleEngineRequest* req = SearchRequests( iSubsId ); + if ( !req ) + { + User::Leave( KErrNotFound ); + } + req->ModifyType( MSimpleEngineRequest::ESubscribeStop ); + + SendReqL( *req ); + + iRequest = MSimpleEngineRequest::ESubscribeStop; + iComplete = EFalse; + iResCount = 0; + + return iOpId; + } + +// ---------------------------------------------------------- +// CSimpleWatcher::StreamDocumentL +// ---------------------------------------------------------- +// +void CSimpleWatcher::StreamDocumentL( + CSimpleEngineRequest& aReq, + MSimpleFilterDocument& aFilter ) + { + // add request data + // externalize the document a stream + iBuffer->Reset(); + RBufWriteStream stream( *iBuffer ); + stream.Open( *iBuffer ); + aFilter.ExternalizeL( stream ); + stream.Close(); + aReq.SetRequestData( iBuffer->Ptr(0) ); + } + +// ---------------------------------------------------------- +// CSimpleWatcher::DoCallReqComplete +// ---------------------------------------------------------- +// +TInt CSimpleWatcher::DoCallReqComplete( + TInt aOpId, TInt aStatus ) + { + // Set the member to point to stack variable + TBool destroyed( EFalse ); + iDestroyedPtr = &destroyed; + + iComplete = ETrue; +#ifdef _DEBUG + TSimpleLogger::Log(_L("Watcher: call WatcherReqCompleteL opid=%d status=%d"), + aOpId, aStatus); +#endif + TRAP_IGNORE( iObserver.WatcherReqCompleteL( aOpId, aStatus )); + // Check whether an application has called destructor in callback method. + // Destructor will handle deletion of all the open requests. + if ( destroyed ) + { + return KErrGeneral; + } + return KErrNone; + } +