bluetoothengine/bthid/bthidserver/src/socketinitiator.cpp
changeset 0 f63038272f30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bthid/bthidserver/src/socketinitiator.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2008 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:  This is the implementation of application class
+ *
+*/
+
+#include <e32debug.h>
+#include "hiddebug.h"
+#include "socketinitiator.h"
+#include "sockinitnotifier.h"
+#include "timeouttimer.h"
+#include "bthidtypes.h"
+#include "sockets.pan"
+#include "debug.h"
+// The transport protocol of the sockets used by this object.
+_LIT(KTransportProtocol, "L2CAP");
+
+// 60*2 seconds socket connect time-out (initially this was 10 seconds, but was changed due to end-user feedback)
+const TInt CSocketInitiator::KTimeOut = 120000000;
+
+CSocketInitiator* CSocketInitiator::NewL(RSocketServ& aSocketServ,
+        MSockInitNotifier& aNotifier)
+    {
+    CSocketInitiator* self = NewLC(aSocketServ, aNotifier);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CSocketInitiator* CSocketInitiator::NewLC(RSocketServ& aSocketServ,
+        MSockInitNotifier& aNotifier)
+    {
+    CSocketInitiator* self = new (ELeave) CSocketInitiator(aSocketServ,
+            aNotifier);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+CSocketInitiator::CSocketInitiator(RSocketServ& aSocketServ,
+        MSockInitNotifier& aNotifier) :
+    CActive(CActive::EPriorityStandard), iSocketServ(aSocketServ), iNotifier(
+            aNotifier), iState(EIdle)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+CSocketInitiator::~CSocketInitiator()
+    {
+        TRACE_INFO((_L("[BTHID]\tCSocketInitiator::~CSocketInitiator()")));
+    Cancel(); // Causes DoCancel
+
+    delete iTimer;
+    }
+
+void CSocketInitiator::ConnectSocketsL(const TBTDevAddr& aAddress,
+        TBool aUseSecurity, RSocket* aControlSocket,
+        RSocket* aInterruptSocket)
+    {
+        TRACE_INFO((_L("[BTHID]\tCSocketInitiator::ConnectSocketsL")));
+    // Store the params for later
+    iControlSocket = aControlSocket;
+    iInterruptSocket = aInterruptSocket;
+    iUseSecurity = aUseSecurity;
+
+    // First close the sockets
+    iControlSocket->Close();
+    iInterruptSocket->Close();
+
+    // Try to open the sockets as L2CAP
+    User::LeaveIfError(iControlSocket->Open(iSocketServ, KTransportProtocol));
+    User::LeaveIfError(
+            iInterruptSocket->Open(iSocketServ, KTransportProtocol));
+
+    iSockAddress.SetBTAddr(aAddress);
+    // First connect the control channel
+    iSockAddress.SetPort(KL2CAPHidControl);
+
+    // Set security requirements for the Control channel.
+    TBTServiceSecurity sec;
+    sec.SetAuthentication(aUseSecurity); //Require authentication
+    sec.SetEncryption(aUseSecurity); //and encryption.
+    sec.SetAuthorisation(EFalse); //and authorisation (This not needed for out-going connections)
+    iSockAddress.SetSecurity(sec);
+
+    // Start a timer to timeout the connect request
+    if (!iTimer->IsActive())
+        iTimer->After(KTimeOut);
+    // Issue the connect request
+    iControlSocket->Connect(iSockAddress, iStatus);
+    // Update the connect state
+    iState = EConnectingControl;
+
+#ifdef __WINS__
+
+    User::After(1); // Fix to allow emulator client to connect to server
+#endif
+
+    // Start this active object
+    SetActive();
+    }
+
+void CSocketInitiator::TimerExpired()
+    {
+        TRACE_INFO((_L("[BTHID]\tCSocketInitiator::TimerExpired()")));
+    // Cancel the operation in progress
+    Cancel();
+    // Inform the observer of this object that a failure occurred
+    // due to a timeout
+    iNotifier.SocketsConnFailed(KErrTimedOut);
+    }
+
+void CSocketInitiator::ConstructL()
+    {
+    // Create a timer
+    iTimer = CTimeOutTimer::NewL(EPriorityStandard, *this);
+    }
+
+void CSocketInitiator::DoCancel()
+    {
+        TRACE_INFO((_L("[BTHID]\tCSocketInitiator::DoCancel()")));
+
+    // Cancel appropriate request
+    switch (iState)
+        {
+        case EConnectingControl:
+            {
+            iControlSocket->CancelConnect();
+            break;
+            }
+        case EConnectingInterrupt:
+            {
+            iInterruptSocket->CancelConnect();
+            break;
+            }
+        default:
+            {
+            User::Panic(KPanicBTConnection, ESocketsBadStatus);
+            break;
+            }
+        }
+
+    //Close the sockets
+    iInterruptSocket->Close();
+    iControlSocket->Close();
+
+    // Set the connect state back to idle
+    iState = EIdle;
+    }
+
+void CSocketInitiator::RunL()
+    {
+    // Cancel any outstanding timer
+    iTimer->Cancel();
+
+    // Any error stops us dead.
+    if (iStatus != KErrNone)
+        {
+        //Close the sockets
+        iControlSocket->Close();
+        iInterruptSocket->Close();
+
+        // Set the connect state back to idle
+        iState = EIdle;
+        // Inform the observer that a failure occurred
+        iNotifier.SocketsConnFailed(iStatus.Int());
+        }
+    else
+        {
+        switch (iState)
+            {
+            case EConnectingControl:
+                {
+                    TRACE_INFO((_L("[BTHID]\tCSocketInitiator::RunL(): Control channel connection request")));
+                ConnectInterruptSocket();
+                }
+                break;
+
+            case EConnectingInterrupt:
+                // L2CAP Interrupt channel connection request
+                // We are connected
+                // Set the connect state back to idle
+                {
+                    TRACE_INFO((_L("[BTHID]\tCSocketInitiator::RunL(): Interrupt channel connection request")));
+                iState = EIdle;
+                // Inform the observer that connection is complete
+                iNotifier.SocketsConnected();
+                break;
+                }
+
+            default:
+                {
+                User::Panic(KPanicBTConnection, ESocketsBadState);
+                break;
+                }
+
+            };
+        }
+    }
+
+void CSocketInitiator::ConnectInterruptSocket()
+    {
+        // Connect the interrupt channel.
+        TRACE_INFO((_L("[BTHID]\tCSocketInitiator::ConnectInterruptSocket()")));
+    ///for BT Stack v2.0, use authentication and encryption
+    TBTServiceSecurity sec;
+    sec.SetAuthentication(iUseSecurity); // 2nd L2cap channel should need no authentication.
+    sec.SetEncryption(iUseSecurity); // but we need encryption.
+    iSockAddress.SetSecurity(sec);
+    ////
+    iSockAddress.SetPort(KL2CAPHidInterrupt);
+
+    // Start a timer to timeout the connect request
+    if (!iTimer->IsActive())
+        iTimer->After(KTimeOut);
+    // Issue the connect request
+    iInterruptSocket->Connect(iSockAddress, iStatus);
+    // Update the connect state
+    iState = EConnectingInterrupt;
+
+#ifdef __WINS__
+
+    User::After(1); // Fix to allow emulator client to connect to server
+#endif
+
+    SetActive();
+    }