www.pudn.com > Example_BluetoothChat.rar > BluetoothServer.cpp


/** 
* 
* @brief Definition of CBluetoothServer 
* 
* Copyright (c) EMCC Software Ltd 2003 
* @version 1.0 
*/ 
 
// System include 
#include  
#include  
 
// 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 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); 
	}