simpleengine/engine/src/simplewinfowatcher.cpp
changeset 0 c8caa15ef882
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simpleengine/engine/src/simplewinfowatcher.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,407 @@
+/*
+* Copyright (c) 2006 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 <e32std.h>
+#include <s32mem.h>
+
+// own simple
+#include "msimpleconnection.h"
+#include "simplecommon.h"
+#include "simpleenginerequest.h"
+#include "msimplewinfo.h"
+#include "msimplefilterdocument.h"
+#include "msimplewinfoobserver.h"
+#include "simplewinfowatcher.h"
+#include "simplexmlfactory.h"
+#include "simplesipconnection.h"
+#include "simpleerrors.h"
+
+#ifdef _DEBUG
+#include "simpledebugutils.h"
+#endif
+
+const TInt KExpandSize = 512;
+
+// ================= MEMBER FUNCTIONS =======================
+//
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::CSimpleWinfoWatcher
+// ----------------------------------------------------------
+//
+CSimpleWinfoWatcher::CSimpleWinfoWatcher(
+    MSimpleConnection& aConn,
+    MSimpleWinfoObserver& aObserver )
+: CSimpleClient( aConn ),
+  iObserver( aObserver ),
+  iResCount(0), iComplete( EFalse ),
+  iBuffer(NULL)
+    {
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::~CSimpleWinfoWatcher
+// ----------------------------------------------------------
+//
+CSimpleWinfoWatcher::~CSimpleWinfoWatcher()
+    {
+#ifdef _DEBUG
+    TSimpleLogger::Log(_L("WinfoWatcher: Destructor this=%d" ), (TInt)this );
+#endif
+    delete iBuffer;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::ConstructL
+// ----------------------------------------------------------
+//
+void CSimpleWinfoWatcher::ConstructL()
+    {
+    BaseConstructL();
+    iBuffer = CBufFlat::NewL(KExpandSize);
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::NewL
+// ----------------------------------------------------------
+//
+CSimpleWinfoWatcher* CSimpleWinfoWatcher::NewL(
+    MSimpleConnection& aConn,
+    MSimpleWinfoObserver& aObserver )
+    {
+    CSimpleWinfoWatcher* self = new (ELeave) CSimpleWinfoWatcher(
+        aConn, aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+#ifdef _DEBUG
+    TSimpleLogger::Log(_L("WinfoWatcher: NewL this=%d"), (TInt)self );
+#endif    
+    return self;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::Connection
+// ----------------------------------------------------------
+//
+const MSimpleConnection& CSimpleWinfoWatcher::Connection()
+    {
+    return iConn;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::SIPStatus
+// ----------------------------------------------------------
+//
+TUint CSimpleWinfoWatcher::SIPStatus()
+    {
+    return DoSIPStatus();
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::SIPRetryAfter
+// ----------------------------------------------------------
+//
+TUint CSimpleWinfoWatcher::SIPRetryAfter()
+    {
+    return DoRetryAfter();
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::Close
+// ----------------------------------------------------------
+//
+void CSimpleWinfoWatcher::Close( )
+    {
+    delete this;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::NewRequestL
+// ----------------------------------------------------------
+//
+void CSimpleWinfoWatcher::NewRequestL( MSimpleEngineRequest& aReq )
+    {
+    TPtrC8 content = aReq.ResponseData();
+    TPtrC8 contType = aReq.ResponseContentType();
+    TPtrC8 p8;
+    p8.Set( KSimpleWinfoType );
+    TInt mySize = p8.Length();
+
+    if ( !contType.Left(mySize).CompareF(KSimpleWinfoType))
+        {
+        MSimpleWinfo* d = TSimpleXmlFactory::NewWinfoL( content );
+        CleanupClosePushL( *d );
+#ifdef _DEBUG
+        TSimpleLogger::Log(_L("WinfoWatcher: call WinfoNotificationL"));
+#endif
+        iObserver.WinfoNotificationL( *d );
+        CleanupStack::PopAndDestroy( d );
+        }
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::Complete
+// ----------------------------------------------------------
+//
+void CSimpleWinfoWatcher::Complete(
+    TInt aOpId, TInt aStatus, MSimpleEngineRequest& aReq )
+    {
+#ifdef _DEBUG
+    TSimpleLogger::Log(_L("WinfoWatcher: Complete opid=%d, status=%d" ),
+                       aOpId, aStatus );
+#endif
+
+    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 WinfoTerminatedL when needed, i.e. no Stop 
+        if ( orig != MSimpleEngineRequest::ESubscribeStop &&
+             !completeNow )
+            {
+#ifdef _DEBUG
+            TSimpleLogger::Log(_L("WinfoWatcher: call WinfoTerminatedL opid=%d"),
+                aOpId );
+#endif
+            TRAP_IGNORE( iObserver.WinfoTerminatedL( 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;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::SubscribeWatcherListL
+// ----------------------------------------------------------
+//
+TInt CSimpleWinfoWatcher::SubscribeWatcherListL(
+    MSimpleFilterDocument* aFilter )
+    {
+
+    if ( iRequest != MSimpleEngineRequest::ENone )
+        {
+#ifdef _DEBUG
+        TSimpleLogger::Log(_L("winfoWatcher: SubscribeWatcherListL IN-USE **" ) );
+#endif
+        User::Leave( KErrInUse );
+        }
+
+    IncreaseOpId();
+
+#ifdef _DEBUG
+    TSimpleLogger::Log(_L("WinfoWatcher: SubscribeWatcherListL opid=%d"),iOpId);
+#endif
+    CSimpleEngineRequest* req = CSimpleEngineRequest::NewL(
+        *this, MSimpleEngineRequest::ESubscribeWinfo, iOpId );
+    CleanupStack::PushL( req );
+
+    // handle optional filter document
+    if ( aFilter )
+        {
+        StreamDocumentL( *req, *aFilter );
+        }
+
+    SendReqL( *req );
+    iRequestList.AddLast( *req );
+    CleanupStack::Pop( req );
+
+    iRequest = MSimpleEngineRequest::ESubscribeWinfo;
+    iResCount = 0;
+    iSubsId = iOpId;
+
+    return iOpId;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::UnsubscribeL
+// ----------------------------------------------------------
+//
+TInt CSimpleWinfoWatcher::UnsubscribeL( )
+    {
+
+#ifdef _DEBUG
+    TSimpleLogger::Log(_L("WinfoWatcher: 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;
+    }
+
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::StreamDocumentL
+// ----------------------------------------------------------
+//
+void CSimpleWinfoWatcher::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) );
+    }
+    
+// ----------------------------------------------------------
+// CSimpleWinfoWatcher::DoCallReqComplete
+// ----------------------------------------------------------
+//
+TInt CSimpleWinfoWatcher::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("WinfoWatcher: call WinfoReqCompleteL opid=%d status=%d"),
+        aOpId, aStatus);
+#endif
+    TRAP_IGNORE( iObserver.WinfoReqCompleteL( 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; 
+    }
+