libraries/btserial/src/connection/btservice.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Sat, 31 Jul 2010 19:07:57 +0100
changeset 23 092bcc217d9d
parent 0 7f656887cf89
permissions -rw-r--r--
Tidied iocli exports, build macro tweaks. Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll. fixed builds on platforms that don't support btrace or any form of tracing.

// Copyright (c) 2004-2009 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:
// Accenture - modified for fshell's btincomingserial.dll
//
// Description:
// Name     : CBtService.cpp
// Part of  : ex_btsocket
// Created  : 17/11/2004 by Shane Kearns
// Server "smart connector" class
// Version  :
// 
//

#include "btservice.h"
#include "btdebug.h"
#include "btincomingserial.h"

/**
Standard Symbian style 2 phase construction
@param aServiceUUID a universally unique identifier for this application.
@param aSdpSession a constructed sdp session owned by the application
@param aSocketServer a constructed socket server session owned by the application
@param aOwner the owning class which should receive notification of new connections
@param aProtocol the protocol (RFCOMM or L2CAP) to register
@param aSecurity optional security settings to use on the socket instead of system defaults
*/
CBtService* CBtService::NewL(const TUUID& aServiceUUID, 
							 RSdp& aSdpSession, 
							 RSocketServ& aSocketServer, 
							 CBluetoothIncomingSerialConnection& aOwner,
							 TUint aProtocol,
							 const TBTServiceSecurity* aSecurity)
	{
	TRACE1("+CBtService::NewL");
	__ASSERT_ALWAYS(aProtocol == KL2CAP || aProtocol == KRFCOMM, PANIC());
	CBtService* self = new(ELeave) CBtService(aSocketServer, aOwner, aProtocol);
	CleanupStack::PushL(self);
	self->ConstructL(aServiceUUID, aSdpSession, aSecurity);
	CleanupStack::Pop(self);
	TRACE1("-CBtService::NewL");
	return self;
	}

/**
Standard 1st phase constructor, inialise member variables
*/
CBtService::CBtService(RSocketServ& aSocketServer, CBluetoothIncomingSerialConnection& aOwner, TUint aProtocol) :
	iSocketServer(aSocketServer),
	iOwner(aOwner),
	iProtocol(aProtocol)
	{
	TRACE2("CBtService::CBtService@%08x", this);
	}

/**
Standard 2nd phase constructor, perform initialisation which could leave
*/
void CBtService::ConstructL(const TUUID& aServiceUUID, RSdp& aSdpSession, const TBTServiceSecurity* aSecurity)
	{
	TRACE1("+CBtService::ConstructL");

	//open handle so it is certain to be valid in the destructor
	User::LeaveIfError(iServiceRecord.Open(aSdpSession));

	//First, create a listening socket
	if(iProtocol == KL2CAP)
		{
		iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockSeqPacket, KL2CAP);
		//bind the socket to a port
		TL2CAPSockAddr addr;
		addr.SetPort(KL2CAPPassiveAutoBind); //allow the stack to choose a free port automatically
		if(aSecurity)
			{
			addr.SetSecurity(*aSecurity); //set security requirements, if present
			}
		User::LeaveIfError(iAcceptorSocket->Bind(addr));
		}
	else if(iProtocol == KRFCOMM)
		{
		iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockStream, KRFCOMM);
		//bind the socket to a port
		TRfcommSockAddr addr;
		addr.SetPort(KRfcommPassiveAutoBind); //allow the stack to choose a free port automatically
		if(aSecurity)
			{
			addr.SetSecurity(*aSecurity); //set security requirements, if present
			}
		User::LeaveIfError(iAcceptorSocket->Bind(addr));
		}
	User::LeaveIfError(iAcceptorSocket->Listen(1)); 

	//Now, register in the SDP database
	TUint port = iAcceptorSocket->LocalPort(); //get the port chosen by the stack
	TRACE2("Listening for connections on port %d", port);
	iServiceRecord.CreateServiceRecordL(aServiceUUID, iServiceRecordHandle);
	
	// Set attr 4 (protocol list) to L2CAP, and RFCOMM
	CSdpAttrValueDES *attrValDES;

	//This following code is doing these steps
	//1. create a DES (data element set) attribute
	//2. within that list, create a DES for each protocol, L2CAP and optionally RFCOMM
	//3. each protocol is a list of elements, the UUID of the protocol, and the port to connect to.
	//4. the service record is updated to include the new attribute
	//5. discard the attribute we built, as it has been copied to the SDP server
	attrValDES = CSdpAttrValueDES::NewDESL(NULL);
	CleanupStack::PushL(attrValDES);
	if(iProtocol == KL2CAP)
		{
		TRACE1("Registering SDP PDL for L2CAP");
		//This code will register an L2CAP (datagram) service
		attrValDES
			->StartListL()
				->BuildDESL()
					->StartListL()
						->BuildUUIDL(TUUID(TUint16(KL2CAP)))	// L2CAP
						->BuildUintL(TSdpIntBuf<TUint16>(TUint16(port)))	// The Protocol Service Multiplexor (port) for our service
					->EndListL()
			->EndListL();
		}
	else if(iProtocol == KRFCOMM)
		{
		TRACE1("Registering SDP PDL for RFCOMM");
		//This code will register an RFCOMM (stream) service
		attrValDES
			->StartListL()
				->BuildDESL()
					->StartListL()
						->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP
					->EndListL()
				->BuildDESL()
					->StartListL()
						->BuildUUIDL(TUUID(TUint16(KRFCOMM))) // RFCOMM
						->BuildUintL(TSdpIntBuf<TUint8>(TUint8(port)))
					->EndListL()
			->EndListL();
		}
	iServiceRecord.UpdateAttributeL(iServiceRecordHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES);
	CleanupStack::PopAndDestroy(attrValDES);
	attrValDES = NULL;

	_LIT8(KSerialPortServiceName, "Bluetooth Serial Console");
	CSdpAttrValueString* attrVal = CSdpAttrValueString::NewStringL(KSerialPortServiceName);
	CleanupStack::PushL(attrVal);
	iServiceRecord.UpdateAttributeL(iServiceRecordHandle, 
			KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceName, *attrVal);
	CleanupStack::PopAndDestroy(attrVal);
	attrVal = NULL;
	TRACE1("-CBtService::ConstructL");
	}

CBtService::~CBtService()
	{
	TRACE1("CBtService::~CBtService");
	//attempt to remove the SDP record
	TRAP_IGNORE(iServiceRecord.DeleteRecordL(iServiceRecordHandle));
	iServiceRecord.Close();
	delete iAcceptorSocket;
	}

/**
Accept a new connection.
When the incoming connection has been made, HandleAcceptCompleteL() will be called
in this class.
That function informs the owner by calling HandleNewConnection() or HandleConnectFailed()
@param aBlankSocket an empty socket to receive the incoming connection. 
*/
void CBtService::AcceptConnection(CBluetoothSocket& aBlankSocket)
	{
	TRACE1("+CBtService::AcceptConnection");
	__ASSERT_ALWAYS(iConnectionSocket == NULL, PANIC());
	iConnectionSocket = &aBlankSocket;
	iAcceptorSocket->Accept(*iConnectionSocket);
	TRACE1("-CBtService::AcceptConnection");
	}

/**
Callback from CBluetoothSocket when a new incoming connection is complete.
Inform the owner 
*/
void CBtService::HandleAcceptCompleteL(TInt aErr)
	{
	TRACE1("+CBtService::HandleAcceptCompleteL");
	if(aErr == KErrNone)
		{
		iOwner.HandleNewConnection(iConnectionSocket); 
		}
	else
		{
		iOwner.HandleConnectFailed(aErr);
		}
	iConnectionSocket = NULL;
	TRACE1("-CBtService::HandleAcceptCompleteL");
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleConnectCompleteL(TInt /*aErr*/)
	{
	TRACE1("+CBtService::HandleConnectCompleteL");
	PANIC();
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleShutdownCompleteL(TInt /*aErr*/)
	{
	TRACE1("+CBtService::HandleShutdownCompleteL");
	PANIC();
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleSendCompleteL(TInt /*aErr*/)
	{
	TRACE1("+CBtService::HandleSendCompleteL");
	PANIC();
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleReceiveCompleteL(TInt /*aErr*/)
	{
	TRACE1("+CBtService::HandleReceiveCompleteL");
	PANIC();
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleIoctlCompleteL(TInt /*aErr*/)
	{
	TRACE1("+CBtService::HandleIoctlCompleteL");
	PANIC();
	}

/**
This function is not used but must be implemented as it is pure virtual
*/
void CBtService::HandleActivateBasebandEventNotifierCompleteL(TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/)
	{
	TRACE1("+CBtService::HandleActivateBasebandEventNotifierCompleteL");
	PANIC();
	}