bluetoothserver.cpp

来自「series60 应用程序开发的源代码 series60 应用程序开发的源代码」· C++ 代码 · 共 441 行

CPP
441
字号
/**
*
* @brief Definition of CBluetoothServer
*
* Copyright (c) EMCC Software Ltd 2003
* @version 1.0
*/

// System include
#include <bt_sock.h>
#include <s32mem.h>

// User include
#include "BluetoothServer.h"
#include "BluetoothAdvertiser.h"
#include "BluetoothChatApplication.h"

/**
* Constructor.
*
* Set observer and flag to indicate not connected
* Add this active object to the scheduler
*
* @param aObserver reference to MBluetoothObserver
**/
CBluetoothServer::CBluetoothServer(MBluetoothObserver& aObserver)
: CActive(CActive::EPriorityStandard),
  iObserver(aObserver),
  iState(EDisconnected)
{
    CActiveScheduler::Add(this);
}

/**
* Factory Constructor.
* Only available way to construct class.
* This function can leave L
* @param none
* @return new instance of the CBluetoothServer
*/
CBluetoothServer* CBluetoothServer::NewL(MBluetoothObserver& aObserver)
{
    CBluetoothServer* self = NewLC(aObserver);
    CleanupStack::Pop(self);
    return self;
}

/**
* Factory Constructor.
* Only available way to construct class.
* This function can leave L, returning value is on Cleanup Stack C
* @param none
* @return new instance of the CBluetoothServer on Cleanup stack
*/
CBluetoothServer* CBluetoothServer::NewLC(MBluetoothObserver& aObserver)
{
    CBluetoothServer* self = new (ELeave) CBluetoothServer(aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
}

/**
* Destructor.
*
* Cancel this active object, and disconnect the Server
* Delete the advertiser
*
* @param none
* @retval none
**/
CBluetoothServer::~CBluetoothServer()
{
    TRAPD(err,StopL());
    // Panic in debug if this didn't work
    __ASSERT_DEBUG(err == KErrNone, Panic(EErrorStoppingServer));

    Cancel();

    // Close handles
    if (iSecSettingsSession.SubSessionHandle() != 0)
    {
        iSecSettingsSession.Close();
    }
    if (iSecManager.Handle() != 0)
    {
        iSecManager.Close();
    }
    if (iAcceptedSocket.SubSessionHandle() != 0)
    {
        iAcceptedSocket.Close();
    }
    if (iListeningSocket.SubSessionHandle() != 0)
    {
        iListeningSocket.Close();
    }
    if (iSocketServer.Handle() != 0)
    {
        iSocketServer.Close();
    }

    delete iAdvertiser;
}

/**
* ConstructL
*
* Create the advertiser
*
* @see NewL
* @see NewLC
* @param none
* @return none
**/
void CBluetoothServer::ConstructL()
{
    iAdvertiser = CBluetoothAdvertiser::NewL();
}

void CBluetoothServer::DoCancel()
{
    switch(iState)
    {
        case EDisconnected :
        {
            break;
        }
        case ESettingSecurity :
        {
            iSecSettingsSession.CancelRequest(iStatus);    // not asynch call
            break;
        }
        case EConnecting :
        {
            iListeningSocket.CancelAccept();
            break;
        }
        case EConnected :
        {
            break;
        }
        case EWaitingForMessage :
        {
            iAcceptedSocket.CancelRecv();
            break;
        }
        case ESendData :
        {
            iAcceptedSocket.CancelSend();
            break;
        }
        default:
        {
            break;
        }
    }
}

/**
* StartServerL.
*
* Connect to Socket Server
* Open a listening socket on the Server on the RFCOMM protocol (KServerTransportName)
* Get a channel to listen on
* Bind the socket to this port, and listen
* Open another socket on the Server
* Issue an asynchronous Accept on the listening socket, passing through the AcceptedSocket
* When the Accept completes the Accepted Socket may be utilised for communication and the listening socket will continue
* listening for connections.
* Set Security options on the Port/Channel
*
* @param none
* @return none
**/
void CBluetoothServer::StartServerL()
{
    if (iState != EDisconnected)
    {
        User::Leave(KErrInUse);
    }

    User::LeaveIfError(iSocketServer.Connect());
    User::LeaveIfError(iListeningSocket.Open(iSocketServer, KServerTransportName));

    // Get a channel to listen on - same as the socket's port number
    User::LeaveIfError(iListeningSocket.GetOpt(KRFCOMMGetAvailableServerChannel, KSolBtRFCOMM, iChannel));

    TBTSockAddr listeningAddress;
    listeningAddress.SetPort(iChannel);

    User::LeaveIfError(iListeningSocket.Bind(listeningAddress));
    User::LeaveIfError(iListeningSocket.Listen(KListeningQueSize));

    SetSecurityOnChannelL(EFalse, EFalse, ETrue);
}

/**
* SetSecurityOnChannelL.
*
* Connect to security manager
* Open a subsession on the security manager used to register settings
* Build the security settings within a TBTServiceSecurity object
* Register these settings
*
* @param aAuthentication true if you wish to enforce authentication
* @param aEncryption true if you wish to enforce encryption on the incomming data
* @param eAuthorisation true if you wish to enforce authorisation.
* @return none
**/
void CBluetoothServer::SetSecurityOnChannelL(TBool aAuthentication, TBool aEncryption, TBool aAuthorisation)
{
    // connect to the security manager and open a settings session.
    User::LeaveIfError(iSecManager.Connect());
    User::LeaveIfError(iSecSettingsSession.Open(iSecManager));

    // the security settings
    TBTServiceSecurity serviceSecurity(KUidBluetoothChat, KSolBtRFCOMM, 0);

    //Define security requirements
    serviceSecurity.SetAuthentication(aAuthentication);
    serviceSecurity.SetEncryption(aEncryption);
    serviceSecurity.SetAuthorisation(aAuthorisation);

    serviceSecurity.SetChannelID(iChannel);

    // make asynch request
    iSecSettingsSession.RegisterService(serviceSecurity, iStatus);
    iState = ESettingSecurity;
    SetActive();
}


/**
* AcceptConnectionsL.
*
* Sets the socket which should be used to accept incoming connections at the
* listening socket.
*
* @param none
* @return none
**/
void CBluetoothServer::AcceptConnectionsL()
{
    iAcceptedSocket.Close();    // close old connection - if any
    User::LeaveIfError(iAcceptedSocket.Open(iSocketServer));    // Open abstract socket

    iState = EConnecting;

    // set the listening socket to accept new connections on
    // the accepted socket.
    iListeningSocket.Accept(iAcceptedSocket, iStatus);

    SetActive();

    // notify the observer that the server has started
    iObserver.ServerStartedL();
}

/**
* StartAdvertisingL.
*
* Start Advertising
*
* @param none
* @return none
**/
void CBluetoothServer::StartAdvertisingL()
{
    iAdvertiser->StartAdvertisingL(iChannel);
    iAdvertiser->UpdateAvailabilityL(ETrue);
}

/**
* StopL.
*
* Stop Advertising
* Close the communication socket
* Close the listening socket
* Close the connection to the socket server
*
* @param none
* @return none
**/
void CBluetoothServer::StopL()
{
    if (iState != EDisconnected)
    {
        if (iAdvertiser->IsAdvertising())
        {
            iAdvertiser->StopAdvertisingL();
        }

        iAcceptedSocket.Close();
        iListeningSocket.Close();
        iSocketServer.Close();
    }

    iState = EDisconnected;
}

/**
* SendL.
*
* Issue an asynchronous Write on the socket, passing through the message to send
*
* @param aMessage the message to send the client
* @return none
**/
void CBluetoothServer::Send(const TDesC& aMessage)
{
    TRAPD(err, SendL(aMessage));
}

void CBluetoothServer::SendL(const TDesC& aMessage)
{
    iMessage.Zero();
    TDesBuf buffer;    
    buffer.Set (iMessage);
    
    RWriteStream stream(&buffer);
    CleanupClosePushL(stream);

    stream << aMessage;
    
    CleanupStack::PopAndDestroy();

    iState = ESendData;
    iAcceptedSocket.Write(iMessage, iStatus);
    SetActive();
}

/**
* RequestData.
*
* Issue an asynchronous receive function on the socket, passing through a buffer to be populated
* @param none
* @return none
**/
void CBluetoothServer::RequestData()
{
    iMessage.Zero();

    iState = EWaitingForMessage;
    iAcceptedSocket.RecvOneOrMore(iMessage, 0, iStatus, iLen);
    SetActive();
}

/**
* RunL
*
* Called when an asynchronous request completes.
* iStatus variable indicates error conditions
* iState indicates present state of the Server
*
* @param none
* @return none
**/
void CBluetoothServer::RunL()
{
    if (iStatus.Int() == KErrNone)
    {
        switch (iState)
        {
            case ESettingSecurity :
            {
                // cleanup after security settings
                iSecSettingsSession.Close();
                iSecManager.Close();

                // accept connections
                AcceptConnectionsL();
                break;
            }
            case EConnecting:
            {
                iObserver.ConnectedL();
                // do not accept any more connections
                iAdvertiser->StopAdvertisingL();
                RequestData();
                break;
            }

            case EWaitingForMessage:
            {
                iState = EConnected;
                TDesBuf buffer;    
                buffer.Set (iMessage);

                RReadStream stream (&buffer);
                CleanupClosePushL(stream);

                TBuf<KMaxMessageLength> rxBuf;

                stream >> rxBuf;

                CleanupStack::PopAndDestroy();

                iObserver.DataReceivedL(rxBuf);
                break;
            }

            case ESendData:
            {
                RequestData();
                break;
            }

            default:
                Panic(EInvalidServerState);
                break;
        }
    }
    else
    {
        StopL();
        iObserver.HandleErrorL(iStatus.Int());
    }
}

/**
 * Returns information on state of the Bluetooth Server.
 *
 * @param none
 * @returns boolean, true if the server is connected to a client, false otherwise
 */
TBool CBluetoothServer::IsConnected()
{
    return !(iState == EDisconnected);
}

/**
 * Returns information on state of the Bluetooth Server.
 *
 * @param none
 * @returns boolean, true if the server is able to send data to the client, false otherwise
 */
TBool CBluetoothServer::AvailableToSend()
{
    return (iState == EConnected);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?