codhandler/codeng/src/Connection.cpp
changeset 0 dd21522fd290
child 28 d39add9822e2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/codhandler/codeng/src/Connection.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,317 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*      Implementation of class CConnection.   
+*      
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "Connection.h"
+#include "CodPanic.h"
+#include "CodUtil.h"
+#include "CodError.h"
+#include "CodLogger.h"
+#include <CommDbConnPref.h>
+#include <cdblen.h>
+#include <es_enum.h>
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CConnection::NewL()
+// ---------------------------------------------------------
+//
+CConnection* CConnection::NewL()
+    {
+    CConnection* conn = new (ELeave) CConnection();
+    CleanupStack::PushL( conn );
+    conn->ConstructL();
+    CleanupStack::Pop( conn );
+    return conn;
+    }
+
+// ---------------------------------------------------------
+// CConnection::~CConnection()
+// ---------------------------------------------------------
+//
+CConnection::~CConnection()
+    {
+    Cancel();
+    DoClose();
+    }
+
+// ---------------------------------------------------------
+// CConnection::ConnectL()
+// ---------------------------------------------------------
+//
+void CConnection::ConnectL( TUint32 aIap, TRequestStatus* aStatus )
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::ConnectL iap(%d)"), aIap ));
+    // Misuse asserts.
+    __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
+    // Internal asserts.
+    __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
+
+    iStatus = KErrCodCannotConnect;
+    if ( iState == EConnected )
+        {
+        // Already connected; do nothing.
+        CLOG(( EConn, 4, _L("  already connected") ));
+        iStatus = KErrNone;
+        }
+    else if ( iState == EInit )
+        {
+        // Not connected. Create connection.
+        CLOG(( EConn, 4, _L("  starting connection") ));
+        // Make this part atomic by pushing closes on the stack.
+        User::LeaveIfError( iSockServ.Connect() );
+        CleanupClosePushL<RSocketServ>( iSockServ );
+        User::LeaveIfError( iConn.Open( iSockServ ) );
+        CleanupClosePushL<RConnection>( iConn );
+        iConnPref.SetDirection( ECommDbConnectionDirectionOutgoing );
+        if ( aIap )
+            {
+            // Use specified IAP.
+            iConnPref.SetIapId( aIap );
+            iConnPref.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+            }
+        else
+            {
+            // aIap == 0 -> user select.
+            iConnPref.SetDialogPreference( ECommDbDialogPrefPrompt );
+            }
+        iConn.Start( iConnPref, iStatus );
+        iState = EConnecting;
+        SetActive();
+        CleanupStack::Pop( 2 ); // closing iConn and iSockServ
+        // End of atomic part.
+        }
+    else
+        {
+        // Not expecting this to be called in other states.
+        CLOG(( EConn, 0, _L("CConnection::ConnectL: unexpected state (%d)"), \
+                                                                    iState ));
+        __ASSERT_ALWAYS( EFalse, CodPanic( ECodInternal ) );
+        }
+
+    iParentStatus = aStatus;
+    *iParentStatus = KRequestPending;
+
+    if ( !IsActive() )
+        {
+        // Unless we have an outstanding connect request (iConn.Start),
+        // we are done.
+        Done();
+        }
+
+    CLOG(( EConn, 2, _L("<- CConnection::ConnectL") ));
+    }
+
+// ---------------------------------------------------------
+// CConnection::AttachL()
+// ---------------------------------------------------------
+//
+void CConnection::AttachL( TUint32 aIap )
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::AttachL iap(%d)"), aIap ));
+
+    iStatus = KErrCodCannotConnect;
+    if ( iState == EConnected )
+        {
+        // Already connected; do nothing.
+        CLOG(( EConn, 4, _L("  already connected") ));
+        iStatus = KErrNone;
+        }
+    else if ( iState == EInit )
+        {
+        // Not connected. Create connection, or attach to existing.
+        CLOG(( EConn, 4, _L("  not connected") ));
+        if ( aIap )
+            {
+            // Make this part atomic by pushing closes on the stack.
+            User::LeaveIfError( iSockServ.Connect() );
+            CleanupClosePushL<RSocketServ>( iSockServ );
+            User::LeaveIfError( iConn.Open( iSockServ ) );
+            CleanupClosePushL<RConnection>( iConn );
+            TConnectionInfoBuf connInfo;
+            TUint count;
+            User::LeaveIfError( iConn.EnumerateConnections( count ) );
+            CLOG(( EConn, 4, _L("  %d existing connections"), count ));
+            TUint i;
+            for ( i = count; i; i-- )
+                {
+                // Note: GetConnectionInfo expects 1-based index.
+                User::LeaveIfError( iConn.GetConnectionInfo( i, connInfo ) );
+                CLOG(( EConn, 4, _L("  conn(%d) iap(%d)"), \
+                                                i, connInfo().iIapId ));
+                if ( connInfo().iIapId == aIap )
+                    {
+                    CLOG(( EConn, 4, _L("  attach"), i, count ));
+                    User::LeaveIfError( iConn.Attach
+                        ( connInfo, RConnection::EAttachTypeNormal ) );
+                    iState = EConnected;
+                    iStatus = KErrNone;
+                    break;
+                    }
+                }
+            CleanupStack::Pop( 2 ); // closing iConn and iSockServ
+            // End of atomic part.
+            }
+        if ( iState == EInit )
+            {
+            CLOG(( EConn, 4, _L("  ended unconnected") ));
+            iConn.Close();
+            iSockServ.Close();
+            }
+        }
+    else
+        {
+        // Not expecting this to be called in other states.
+        CLOG(( EConn, 0, _L("CConnection::AttachL: unexpected state (%d)"), \
+                                                                    iState ));
+        __ASSERT_ALWAYS( EFalse, CodPanic( ECodInternal ) );
+        }
+    User::LeaveIfError( iStatus.Int() );
+
+    CLOG(( EConn, 2, _L("<- CConnection::AttachL") ));
+    }
+
+// ---------------------------------------------------------
+// CConnection::Close()
+// ---------------------------------------------------------
+//
+void CConnection::Close()
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::Close") ));
+    Cancel();
+    DoClose();
+    CLOG(( EConn, 2, _L("<- CConnection::Close") ));
+    }
+
+// ---------------------------------------------------------
+// CConnection::IsConnected()
+// ---------------------------------------------------------
+//
+TBool CConnection::IsConnected( TUint32& aIap )
+    {
+    TBool connected( EFalse );
+    if( iState == EConnected )
+        {
+        TBuf<KCommsDbSvrMaxColumnNameLength * 2 + 1> iapId;
+        _LIT( KFormatIapId, "%S\\%S" );
+        TPtrC iap( IAP );
+        TPtrC id( COMMDB_ID );
+        iapId.Format( KFormatIapId, &iap, &id );
+        TInt err = iConn.GetIntSetting( iapId, aIap );
+        connected = err ? EFalse : ETrue;
+        }
+    return connected;
+    }
+
+// ---------------------------------------------------------
+// CConnection::CConnection()
+// ---------------------------------------------------------
+//
+CConnection::CConnection()
+: CActive( CActive::EPriorityStandard ),
+  iState( EInit )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------
+// CConnection::ConstructL()
+// ---------------------------------------------------------
+//
+void CConnection::ConstructL()
+    {
+    if ( !CodUtil::ApCountL() )
+        {
+        // It's futile to try making a connection without an AP, so leave if
+        // we don't have any.
+        User::Leave( KErrCodNoAccessPoint );
+        }
+    }
+
+// ---------------------------------------------------------
+// CConnection::DoCancel()
+// ---------------------------------------------------------
+//
+void CConnection::DoCancel()
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::DoCancel") ));
+    __ASSERT_DEBUG( iState == EConnecting, CodPanic( ECodInternal ) );
+    // RConnection has no cancel method matching the async RConnection::Start.
+    // The only way to cancel is to close the RConnection.
+    // (Our request will complete with KErrCancel, as expected.)
+    DoClose();
+    Done();
+    CLOG(( EConn, 2, _L("<- CConnection::DoCancel") ));
+    }
+
+// ---------------------------------------------------------
+// CConnection::RunL()
+// ---------------------------------------------------------
+//
+void CConnection::RunL()
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::RunL iStatus(%d)"), \
+        iStatus.Int() ));
+    __ASSERT_DEBUG( iState == EConnecting, CodPanic( ECodInternal ) );
+    User::LeaveIfError( iStatus.Int() );    // Handle errors in RunError().
+    iState = EConnected;
+    Done();
+    CLOG(( EConn, 2, _L("<- CConnection::RunL") ));
+    }
+
+// ---------------------------------------------------------
+// CConnection::RunError()
+// ---------------------------------------------------------
+//
+TInt CConnection::RunError( TInt LOG_ONLY( aError ) )
+    {
+    CLOG(( EConn, 2, _L("-> CConnection::RunError aError(%d)"), aError ));
+    __ASSERT_DEBUG( iState == EConnecting, CodPanic( ECodInternal ) );
+    DoClose();
+    Done();
+    CLOG(( EConn, 2, _L("<- CConnection::RunError") ));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CConnection::DoClose()
+// ---------------------------------------------------------
+//
+void CConnection::DoClose()
+    {
+    CLOG(( EConn, 2, _L("CConnection::DoClose") ));
+    iConn.Close();
+    iSockServ.Close();
+    iState = EInit;
+    }
+
+// ---------------------------------------------------------
+// CConnection::Done()
+// ---------------------------------------------------------
+//
+void CConnection::Done()
+    {
+    CLOG(( EConn, 2, _L("CConnection::Done iStatus(%d)"), iStatus.Int() ));
+    __ASSERT_DEBUG( iParentStatus, CodPanic( ECodInternal ) );
+    User::RequestComplete( iParentStatus, iStatus.Int() );
+    iParentStatus = NULL;
+    }