javaextensions/bluetooth/bluetoothplugins/btl2cappushplugin/src.s60/btl2capserverconnection.cpp
changeset 21 2a9601315dfc
child 57 59b3b4473dc8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/bluetooth/bluetoothplugins/btl2cappushplugin/src.s60/btl2capserverconnection.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,591 @@
+/*
+* 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:
+*
+*/
+
+
+#include "logger.h"
+#include "functionserver.h"
+#include "bluetoothfunctionserver.h"
+#include "bluetoothremotedevice.h"
+#include "bluetoothclientconnection.h"
+#include "fs_methodcall.h"
+
+#include "btl2capserverconnection.h"
+#include "bluetoothpusheventlistener.h"
+#include "javasymbianoslayer.h"
+#include <e32cmn.h>
+
+using namespace std;
+
+namespace java
+{
+namespace bluetooth
+{
+
+const TInt KSizeOfListenQueue = 7;
+
+OS_EXPORT L2CAPServerConnection::L2CAPServerConnection(
+    java::bluetooth::BluetoothFunctionServer* server):
+        mAcceptMonitor(NULL),
+        mAsyncAccept(false),
+        mAvoidFilter(false),
+        mBtUrlParams(NULL),
+        mBtClientConn(NULL),
+        mServer(server),
+        mIsConnected(EFalse),
+        mServRec(NULL),
+        mState(ENone)
+{
+}
+
+OS_EXPORT L2CAPServerConnection::~L2CAPServerConnection()
+{
+    CloseServer();
+    delete mAcceptMonitor;
+}
+
+OS_EXPORT int L2CAPServerConnection::openServer(bool authorize,
+        bool authenticate, bool encrypt, bool master, int receiveMTU,
+        int transmitMTU)
+{
+    //convert and call ServerOpen()
+    JELOG2(EJavaBluetooth);
+    LOG2(EJavaBluetooth, EInfo,
+         "* L2CAPServerConnection::openServer TxMTU:%d RxMTU:%d",
+         transmitMTU, receiveMTU);
+    return ServerOpen(authorize, authenticate, encrypt, master, receiveMTU,
+                      transmitMTU);
+}
+
+OS_EXPORT int L2CAPServerConnection::ServerOpen(TBool authorize,
+        TBool authenticate, TBool encrypt, TBool master, TInt receiveMTU,
+        TInt transmitMTU)
+{
+    int result = 0;
+    LOG2(EJavaBluetooth, EInfo,
+         "+ L2CAPServerConnection::ServerOpen TxMTU:%d RxMTU:%d",
+         transmitMTU, receiveMTU);
+    TRAP(result, CallMethodL(this, &L2CAPServerConnection::ServerOpenL,
+                             authorize, authenticate, encrypt, master, receiveMTU, transmitMTU,
+                             mServer));
+    return result;
+}
+
+OS_EXPORT ServiceRecord *L2CAPServerConnection::getServiceRecordHandle()
+{
+    return mServRec;
+}
+
+void L2CAPServerConnection::ServerOpenL(TBool authorize, TBool authenticate,
+                                        TBool encrypt, TBool master, TInt receiveMTU, TInt transmitMTU)
+{
+    LOG(EJavaBluetooth, EInfo, "+ L2CAPServerConnection::ServerOpenL ");
+
+    if (mState != ENone)
+    {
+        User::Leave(KErrInUse);
+    }
+
+    User::LeaveIfError(mSocketServ.Connect());
+    User::LeaveIfError(mSocketServ.ShareAuto());
+
+    TRAPD(err,
+    {
+        // Set this active object to connecting state
+        mState = EConnecting;
+
+        // Set a Bluetooth socket address
+        BindL(authorize, authenticate,
+              encrypt, master, receiveMTU, transmitMTU);
+
+        // Set a socket to listen for incoming connections
+        ListenL();
+    }
+         );
+
+    if (KErrNone != err)
+    {
+        mState = ENone;
+        mSocketServ.Close();
+        User::LeaveIfError(err);
+    }
+
+    LOG(EJavaBluetooth, EInfo, "- L2CAPServerConnection::ServerOpenL ");
+}
+
+void L2CAPServerConnection::BindL(TBool authorize, TBool authenticate,
+                                  TBool encrypt, TBool master, TInt receiveMTU, TInt transmitMTU)
+{
+    LOG2(EJavaBluetooth, EInfo,
+         "+ L2CAPServerConnection::BindL TxMTU:%d RxMTU:%d",
+         transmitMTU, receiveMTU);
+    // Load protocol, L2CAP
+    TProtocolDesc protocolDesc;
+    User::LeaveIfError(mSocketServ.FindProtocol(KL2CAPDesC(), protocolDesc));
+
+    LOG(EJavaBluetooth, EInfo,
+        "  L2CAPServerConnection::BindL: Opening A Listerner Socket ");
+    // Open a socket
+    mListenSock = CBluetoothSocket::NewL(*this, mSocketServ,
+                                         protocolDesc.iSockType, KL2CAP);
+
+    // Set security
+    TBTServiceSecurity secSettings;
+
+    secSettings.SetAuthentication(authenticate);
+    secSettings.SetAuthorisation(authorize);
+    secSettings.SetEncryption(encrypt);
+
+    // Later once connection accepted this flag is used to set the role
+    mMasterRoleRequested = master;
+
+    LOG(EJavaBluetooth, EInfo,
+        "  L2CAPServerConnection::BindL: Attaching The Security Settings ");
+    // Attach the security settings.
+    mBtSockAddr.SetSecurity(secSettings);
+
+    if (transmitMTU >= KL2MinMTU || receiveMTU >= KL2MinMTU)
+    {
+        TL2CapConfigPkg options;
+        TInt errMtu = KErrNone;
+
+        if (transmitMTU >= KL2MinMTU)
+        {
+            errMtu = options().SetMaxTransmitUnitSize(transmitMTU);
+            if (KErrNone != errMtu)
+            {
+                ELOG2(EJavaBluetooth,
+                      "  L2CAPServerConnection::BindL: TxMTU(%d) Err:%d",
+                      transmitMTU, errMtu);
+            }
+        }
+        else
+        {
+            errMtu = options().SetMaxTransmitUnitSize(DEFAULT_MTU);
+            if (KErrNone != errMtu)
+            {
+                ELOG2(EJavaBluetooth,
+                      "  L2CAPServerConnection::BindL: Default TxMTU(%d) Err:%d",
+                      transmitMTU, errMtu);
+            }
+        }
+
+        if (receiveMTU >= KL2MinMTU)
+        {
+            errMtu = options().SetMaxReceiveUnitSize(receiveMTU);
+            if (KErrNone != errMtu)
+            {
+                ELOG2(EJavaBluetooth,
+                      "  L2CAPServerConnection::BindL: RxMTU(%d) Err:%d",
+                      receiveMTU, errMtu);
+            }
+        }
+        else
+        {
+            errMtu = options().SetMaxReceiveUnitSize(DEFAULT_MTU);
+            if (KErrNone != errMtu)
+            {
+                ELOG2(EJavaBluetooth,
+                      "  L2CAPServerConnection::BindL: Default RxMTU(%d) Err:%d",
+                      receiveMTU, errMtu);
+            }
+        }
+        //L2CAP Specific stuff
+        mListenSock->SetOpt(KL2CAPUpdateChannelConfig, KSolBtL2CAP, options);
+    }
+
+    // Setting l2cap passive port
+    mBtSockAddr.SetPort(KL2CAPPassiveAutoBind);
+
+    LOG(EJavaBluetooth, EInfo,
+        "  L2CAPServerConnection::BindL: Binding Bluetooth Socket ");
+    // Bind bluetooth socket
+    User::LeaveIfError(mListenSock->Bind(mBtSockAddr));
+    LOG(EJavaBluetooth, EInfo, "- L2CAPServerConnection::BindL");
+}
+
+OS_EXPORT int L2CAPServerConnection::GetServerPSM()
+{
+    int result = 0;
+    CallMethod(result, this, &L2CAPServerConnection::GetServerPSMValue, mServer);
+    return result;
+}
+
+int L2CAPServerConnection::GetServerPSMValue()
+{
+    JELOG2(EJavaBluetooth);
+    if (mState != EConnecting)
+    {
+        return -1;
+    }
+    return mListenSock->LocalPort();
+}
+
+void L2CAPServerConnection::ListenL()
+{
+    JELOG2(EJavaBluetooth);
+    // Listen on port
+    User::LeaveIfError(mListenSock->Listen(KSizeOfListenQueue));
+}
+
+OS_EXPORT int L2CAPServerConnection::asyncAccept(
+    java::bluetooth::BluetoothPushEventListener* aEventListener,
+    BtUrlParams *aBtUrlParams)
+{
+    JELOG2(EJavaBluetooth);
+    //Store event listener and notify it when client is accepted.
+    //Make a call to accept and do not wait.
+    mAsyncAccept = true;
+    mPushEventListener = aEventListener;
+    mBtUrlParams = aBtUrlParams;
+    int result = 0;
+    TRAPD(err, CallMethodL(result, this, &L2CAPServerConnection::AcceptL,
+                           mServer));
+    return err;
+}
+
+OS_EXPORT long L2CAPServerConnection::Accept()
+{
+    JELOG2(EJavaBluetooth);
+    long result = 0;
+    mBtClientConn = NULL;
+
+    TRAPD(err, CallMethodL(result, this, &L2CAPServerConnection::AcceptL,
+                           mServer));
+
+    if (err != KErrNone)
+    {
+        return err;
+    }
+
+    mAcceptMonitor->wait();
+
+    if (mAcceptStatus != KErrNone)
+    {
+        return mAcceptStatus;
+    }
+
+    mAcceptedSocket = NULL;
+
+    return reinterpret_cast<long>(mBtClientConn);
+}
+
+long L2CAPServerConnection::AcceptL()
+{
+    JELOG2(EJavaBluetooth);
+
+    // Open blank socket and pass it to accept to be assigned a proper
+    // socket upon completion of Accept()
+    mAcceptedSocket = CBluetoothSocket::NewL(*this, mSocketServ);
+    LOG(EJavaBluetooth, EInfo,
+        "  L2CAPServerConnection::Accept: Set To Accept Incoming Connections ");
+
+    if (NULL == mAcceptMonitor)
+    {
+        mAcceptMonitor = java::util::Monitor::createMonitor();
+    }
+
+    if (true == mMasterRoleRequested)
+    {
+        if (KErrNone == mAcceptedSocket->RequestMasterRole())
+        {
+            LOG(EJavaBluetooth, EInfo,
+                "  L2CAPServerConnection::Accept: Added the master role");
+        }
+    }
+    mAcceptStatus = 0;
+
+    // Enabling the advertising flag
+    if (NULL != mServRec)
+    {
+        mServRec -> setAdvertiseFs(ETrue);
+    }
+    // Initiating accepting for the new client connection
+    mListenSock->Accept((*mAcceptedSocket));
+
+    return 0;
+}
+
+OS_EXPORT int L2CAPServerConnection::initializeServiceRecord(
+    TInt aPsmValue, TUUID &aServiceUUID, TDesC8 &aServiceName)
+{
+    JELOG2(EJavaBluetooth);
+
+    int result = 0;
+
+    if (NULL == mServRec)
+    {
+        TRAP(result, CallMethodL(mServRec, this,
+                                 &L2CAPServerConnection::createServiceRecordL, mServer));
+
+        if (KErrNone == result)
+        {
+            TInt protocol = PROTOCOL_L2CAP;
+
+            TRAP(result, mServRec->initializeRecordL(protocol,
+                    aPsmValue, aServiceUUID, aServiceName));
+        }
+    }
+
+    return result;
+}
+
+OS_EXPORT int L2CAPServerConnection::initializeServiceRecord(
+    int aPsmValue, wstring aServiceUUID, wstring aServiceName)
+{
+    JELOG2(EJavaBluetooth);
+    int result = 0;
+
+    if (NULL == mServRec)
+    {
+        TRAP(result, CallMethodL(mServRec, this,
+                                 &L2CAPServerConnection::createServiceRecordL, mServer));
+
+        if (KErrNone == result)
+        {
+            result = mServRec->initializeRecord(PROTOCOL_L2CAP,
+                                                aPsmValue, aServiceUUID, aServiceName);
+        }
+    }
+    return result;
+}
+
+OS_EXPORT int L2CAPServerConnection::restorePersistentRecord()
+{
+    JELOG2(EJavaBluetooth);
+    int result = 0;
+
+    if (NULL != mServRec)
+    {
+        result = mServRec->restorePersistentRecord();
+    }
+    return result;
+}
+
+ServiceRecord *L2CAPServerConnection::createServiceRecordL()
+{
+    JELOG2(EJavaBluetooth);
+    return ServiceRecord::NewL(mServer);
+}
+
+int L2CAPServerConnection::CloseServer()
+{
+    JELOG2(EJavaBluetooth);
+    int result = 0;
+    mIsConnected = EFalse;
+    mAsyncAccept = false;
+    CallMethod(this, &L2CAPServerConnection::Close, mServer);
+    return result;
+}
+
+void L2CAPServerConnection::Close()
+{
+    JELOG2(EJavaBluetooth);
+
+    // Deleting service record.
+    ServiceRecord::cleanup(mServRec);
+
+    if (mState != ENone)
+    {
+        LOG(EJavaBluetooth, EInfo, "  L2CAPServerConnection::Close ");
+        mListenSock->CancelAll();
+        mListenSock->Shutdown(RSocket::EImmediate);
+        delete mListenSock; //Destructor closes the socket
+        mListenSock = NULL;
+        mState = ENone;
+        mAcceptStatus = KErrCancel;
+        if (mAcceptMonitor)
+            mAcceptMonitor->notify();
+    }
+}
+
+void L2CAPServerConnection::DoCancel()
+{
+    JELOG2(EJavaBluetooth);
+}
+
+bool L2CAPServerConnection::isConnectionAllowed(TBTSockAddr aBtAddr)
+{
+    JELOG2(EJavaBluetooth);
+    if (NULL == mBtUrlParams)
+    {
+        return true;
+    }
+
+    bool authorize = false;
+    bool authenticate = false;
+
+    HBufC* devAddr = HBufC::New(aBtAddr.Length());
+    TPtr ptr = devAddr->Des();
+    TBTDevAddr btDeviceAddress = aBtAddr.BTAddr();
+    btDeviceAddress.GetReadable((TDes&)ptr);
+    if (true == mBtUrlParams->isBlockedSender(*devAddr))
+    {
+        delete devAddr;
+        return false;
+    }
+    if (true == mBtUrlParams->isAllowedSender(*devAddr, authorize, authenticate))
+    {
+        LOG(EJavaBluetooth, EInfo,
+            "  L2CAPServerConnection::isConnectionAllowed AllowedSender");
+        bool flag = true;
+        TInt64 longBtAddr = 0;
+        TLex16 toParse(*devAddr);
+        toParse.Val(longBtAddr, EHex);
+        LOG1(EJavaBluetooth, EInfo,
+             " L2CAPServerConnection::isConnectionAllowed Long BTRemote address %llx",longBtAddr);
+        if (true == authorize)
+        {
+            flag = BluetoothRemoteDevice::getSecurityProperty(
+                       REMOTE_AUTHORIZED, longBtAddr);
+        }
+        if (true == flag && true == authenticate)
+        {
+            flag = BluetoothRemoteDevice::getSecurityProperty(
+                       REMOTE_AUTHENTICATED, longBtAddr);
+        }
+        delete devAddr;
+        return flag;
+    }
+    delete devAddr;
+    LOG(EJavaBluetooth, EInfo, "- L2CAPServerConnection::isConnectionAllowed");
+    return false;
+}
+
+//
+void L2CAPServerConnection::avoidFilter()
+{
+    JELOG2(EJavaBluetooth);
+    mAvoidFilter = true;
+}
+//------------------------------------------------------------------------------
+//  Methods from MBluetoothSocketNotifier to handle Bluetooth Events
+//------------------------------------------------------------------------------
+
+//Notification of an accept complete event
+void L2CAPServerConnection::HandleAcceptCompleteL(TInt err)
+{
+    TBTSockAddr btRemoteAddr;
+    int negotiatedReceiveMtu = 0;
+    int negotiatedTransmitMtu = 0;
+
+    mAcceptStatus = err;
+
+    LOG1(EJavaBluetooth, EInfo, "+  L2CAPServerConnection::HandleAcceptCompleteL Err:%d", err);
+
+    if (KErrNone == err)
+    {
+        mAcceptedSocket->RemoteName(btRemoteAddr);
+        if (mAsyncAccept && (!mAvoidFilter) && (false == isConnectionAllowed(btRemoteAddr)))
+        {
+            mAcceptedSocket->CancelAll();
+            mAcceptedSocket->Shutdown(RSocket::EImmediate);
+            delete mAcceptedSocket;
+            mAcceptedSocket = NULL;
+            ELOG(EJavaBluetooth,
+                 "L2CAPServerConnection::HandleAcceptCompleteL Connection Rejected");
+            AcceptL();
+            return;
+        }
+        TBuf<20> addr;
+        TInt64 longBtAddr = 0;
+        TBTDevAddr btDeviceAddress = btRemoteAddr.BTAddr();
+        btDeviceAddress.GetReadable(addr);
+        TLex16 toParse(addr);
+        toParse.Val(longBtAddr, EHex);
+        LOG1(EJavaBluetooth, EInfo,
+             "L2CAPServerConnection::HandleAcceptCompleteL: Address: %ld", longBtAddr);
+        mBtClientConn = new BluetoothClientConnection(mAcceptedSocket, mServer);
+        mAcceptedSocket->GetOpt(KL2CAPInboundMTU, KSolBtL2CAP, negotiatedReceiveMtu);
+        mAcceptedSocket->GetOpt(KL2CAPNegotiatedOutboundMTU, KSolBtL2CAP, negotiatedTransmitMtu);
+        mBtClientConn->initialize(
+            PROTOCOL_L2CAP, longBtAddr, negotiatedReceiveMtu, negotiatedTransmitMtu);
+        if (mAsyncAccept)
+        {
+            mPushEventListener->handleConnectionRequest(mBtClientConn, err);
+        }
+        else
+        {
+            mAcceptMonitor->notify();
+        }
+    }
+    else
+    {
+        if (mAsyncAccept)
+        {
+            // If Push framework cancels the listening then return otherwise
+            // continue listening.
+            if (KErrCancel == err)
+            {
+                mPushEventListener->handleConnectionRequest(NULL, err);
+            }
+            else
+            {
+                ELOG(EJavaBluetooth,
+                     "  L2CAPServerConnection::HandleAcceptCompleteL: Error while accept. Listening again.");
+                AcceptL();
+            }
+            return;
+        }
+        else
+        {
+            mAcceptMonitor->notify();
+        }
+    }
+
+    // If connection accepted, then it should
+    // disable the advertising flag
+    if (NULL != mServRec)
+    {
+        mServRec -> setAdvertiseFs(EFalse);
+    }
+
+    LOG(EJavaBluetooth, EInfo, "-  L2CAPServerConnection::HandleAcceptCompleteL");
+}
+
+// Notification of a baseband event
+void L2CAPServerConnection::HandleActivateBasebandEventNotifierCompleteL(
+    TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/)
+{
+}
+
+//Notification of a connection complete event
+void L2CAPServerConnection::HandleConnectCompleteL(TInt /*aErr*/)
+{
+}
+
+//Notification of a ioctl complete event
+void L2CAPServerConnection::HandleIoctlCompleteL(TInt /*aErr*/)
+{
+}
+
+//Notification of a receive complete event
+void L2CAPServerConnection::HandleReceiveCompleteL(TInt /*aErr*/)
+{
+}
+
+//Notification of a send complete event
+void L2CAPServerConnection::HandleSendCompleteL(TInt /*aErr*/)
+{
+}
+
+//Notification of a shutdown complete event
+void L2CAPServerConnection::HandleShutdownCompleteL(TInt /*aErr*/)
+{
+}
+
+} //end namespace bluetooth
+} //end namespace java