diff -r e8e63152f320 -r 2a9601315dfc javaextensions/bluetooth/bluetoothplugins/btl2cappushplugin/src.s60/btl2capserverconnection.cpp --- /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 + +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(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