ImagePrint/ImagePrintEngine/DeviceProtocols/btprotocol/src/cbtobjectserver.cpp
changeset 0 d11fb78c4374
child 2 acc370d7f2f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ImagePrint/ImagePrintEngine/DeviceProtocols/btprotocol/src/cbtobjectserver.cpp	Thu Dec 17 08:45:53 2009 +0200
@@ -0,0 +1,950 @@
+/*
+* Copyright (c) 2004-2007 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 <avkon.hrh>
+#include <aknnotewrappers.h>
+
+#include "cbtprintingdevice.h"
+#include "cbtobjectserver.h"
+#include "btprotocolconsts.h"
+#include "clog.h"
+#include "printmessagecodes.h"
+#include "tbtmapper.h"
+#include "xhtmlfilecomposerconst.h"
+#include "rsutils.h"
+
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::NewL()
+// Creates a new instance of the class
+// ----------------------------------------------------------------------------
+
+CBtObjectServer* CBtObjectServer::NewL(const TBTDevAddr& aDeviceAddress,
+                                               RArray<CImageInfo> &aImgArray,
+                                               MBtObjectServerObserver &aObs)
+{
+
+    CBtObjectServer* self = CBtObjectServer::NewLC( aDeviceAddress, aImgArray, aObs );
+    CleanupStack::Pop( self );
+    return self;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::NewLC()
+// Creates a new instance of the class
+// ----------------------------------------------------------------------------
+
+CBtObjectServer* CBtObjectServer::NewLC(const TBTDevAddr& aDeviceAddress,
+                                                RArray<CImageInfo> &aImgArray,
+                                                MBtObjectServerObserver &aObs)
+{
+
+    CBtObjectServer* self = new ( ELeave ) CBtObjectServer( aDeviceAddress, aObs );
+    CleanupStack::PushL( self );
+    self->ConstructL(aImgArray);
+    return self;
+
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::CBtObjectServer
+// The actual constructor of the class
+// ----------------------------------------------------------------------------
+
+CBtObjectServer::CBtObjectServer(const TBTDevAddr& aDeviceAddress, MBtObjectServerObserver& aObs )
+:  	iAllowedAddress ( aDeviceAddress ),
+	iObs ( aObs ),
+	iStarted(EFalse),
+	iConnected(EFalse),
+	iTransportUp(EFalse)
+{
+    LOG("CBtObjectServer::CBtObjectServer]\t default constructor");
+
+   iImgArray.Reset();
+   iImgArray.Close();
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::~CBtObjectServer()
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CBtObjectServer::~CBtObjectServer()
+{
+    LOG("CBtObjectServer::~CBtObjectServer]\t");
+
+	iStarted = EFalse;
+	iOperation = EIdle;
+
+    if ( iObexServer && iObexServer->IsStarted() )
+    {
+        iObexServer->Stop();
+    }
+
+	iFs.Close();
+
+    if (iObexServer)
+    	delete iObexServer;
+    iObexServer = NULL;
+
+	if(iObexBufObject)
+    	delete iObexBufObject;
+    iObexBufObject = NULL;
+
+	// This must be deleted after the iObexBufObject who uses it.
+    if (iObexBody)
+	    delete iObexBody;
+    iObexBody = NULL;
+
+	if(iAdvertiser)
+    	delete iAdvertiser;
+    iAdvertiser = NULL;
+
+    iImgArray.Close();
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::Cancel()
+// Sends current file to the server and then stops the server
+// ----------------------------------------------------------------------------
+void CBtObjectServer::Cancel()
+{
+    LOG("[CBtObjectServer::Cancel]\t");
+
+    if (!IsSendingData())
+    {
+        LOG("[CBtObjectServer::Cancel]\t - not sending data - stopping server now! \n");
+        Stop();
+    }
+    else
+    {
+    	iOperation = EIdle;
+    }
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::ConstructL()
+// Constucts everything that can leave in the class
+// ----------------------------------------------------------------------------
+void CBtObjectServer::ConstructL(RArray<CImageInfo> &aImgArray)
+{
+    LOG("[CBtObjectServer::ConstructL]\t");
+
+    LOG1("[CBtObjectServer::ConstructL]\t aImgArray.Count(): %d", aImgArray.Count());
+	for(TInt i = 0; i < aImgArray.Count(); ++i)
+	{
+		iImgArray.Append(aImgArray[i]);
+
+/* For debug		
+#ifdef ENABLE_LOGGING		
+		TFileName8 uri;
+		aImgArray[i].GetUri(uri);
+		TFileName8 log;
+		CImageInfo::UriLog(uri, log);
+    	LOG1("[CBtObjectServer::ConstructL]\t uri: %d", log);
+#endif // ENABLE_LOGGING
+*/
+	}
+
+    iAdvertiser = CBtDprServiceAdvertiser::NewL();
+
+    // create OBEX object to receive obex transfer. 8 for reserving data in 8 bytes segments
+    iObexBody = CBufFlat::NewL( 8 );
+
+    User::LeaveIfError(iFs.Connect());
+
+	InitTransferData();
+	iRemoteAddress.Reset();
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::Stop()
+// Disconnects the server.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::Stop()
+{
+    LOG("[CBtObjectServer::Stop]\t");
+    
+    // already stopping
+    if(!iStarted)
+    	return;
+    
+	iOperation = ETerminating;
+
+    LOG("[CBtObjectServer::Stop]\t cont...");
+    iRemoteAddress.Reset();
+    
+    //cannot delete here. Stop called from iObexServer Callback function.
+    if ( iObexServer && iObexServer->IsStarted())
+    {
+	    LOG("[CBtObjectServer::Stop]\t stopping iObexServer...");
+    	iObexServer->Stop();
+	}
+
+    // Trap this: if it fails, we cannot do anything.
+    TInt leave; // for remove compiling warnings
+    TRAP(leave, iAdvertiser->StopAdvertisingL());
+    LOG1("[CBtObjectServer::Stop]\t iAdvertiser->StopAdvertising() leaves with %d", leave);
+
+    LOG1("[CBtObjectServer::Stop]\t iObexServer: %d", iObexServer);
+
+	iOperation = EIdle; 
+	iStarted = EFalse;
+	iConnected = EFalse;
+	iTransportUp = EFalse;
+
+    /* Sending 'stopped' status */
+    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerStopped);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::StartL()
+// Starts the server.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::StartL()
+{
+    LOG("[CBtObjectServer::StartL]\t");
+
+	TBool btOn = RsUtils::IsBluetoothOn();
+	LOG1("[CBtObjectServer::StartL]\t btOn: %d", btOn);
+	if( !btOn )
+		User::Leave(KErrCancel);
+
+    TRAPD( err, InitialiseServerL() );
+    LOG1("CBtObjectServer::StartL]\t InitialiseServerL leaves with %d", err);
+
+    if ( err != KErrNone )
+    {
+        Stop();
+    	User::Leave(err);
+    }
+
+    iStarted = ETrue;
+
+    /* Send 'server started' status */
+    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerStarted);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::InitialiseServerL()
+// Initialises the server.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::InitialiseServerL()
+{
+    LOG("CBtObjectServer::InitialiseServerL]\t");
+
+    if ( iObexServer )
+    {
+        ASSERT( IsConnected() ); // server already running
+        return;
+    }
+
+    LOG("[CBtObjectServer::InitialiseServerL]\t - getting channel");
+
+	// Set the Socket's security with parameters,
+	// Authentication, Encryption, Authorisation and Denied
+	// Method also return the channel available to listen to.
+	TInt channel = SetSecurityWithChannelL( EFalse, EFalse, EFalse, EFalse );
+
+    // start the OBEX server
+    TObexBluetoothProtocolInfo obexProtocolInfo;
+
+    LOG1("[CBtObjectServer::InitialiseServerL]\t setting %S ", &KRFCOMMDesC);
+    obexProtocolInfo.iTransport.Copy( KRFCOMMDesC() );
+
+    LOG1("[CBtObjectServer::InitialiseServerL]\t setting port %d", channel);
+    obexProtocolInfo.iAddr.SetPort( channel );
+
+    LOG("[CBtObjectServer::InitialiseServerL]\t CObexServer::NewL()");
+    if(iObexServer)
+    {
+    	delete iObexServer;
+    	iObexServer = NULL;
+    }
+    iObexServer = CObexServer::NewL( obexProtocolInfo );
+
+    LOG("[CBtObjectServer::InitialiseServerL]\t iObexServer->Start()");
+    User::LeaveIfError(iObexServer->Start( this ) );
+
+    TUUID who(KBTSDPDPROService);
+	User::LeaveIfError(iObexServer->SetLocalWho(who.LongForm()));
+
+    // advertise this service
+    LOG("[CBtObjectServer::InitialiseServerL]\t iAdvertiser->StartAdvertisingL()");
+    iAdvertiser->StartAdvertisingL( channel );
+    LOG("[CBtObjectServer::InitialiseServerL]\t iAdvertiser->UpdateAvailabilityL()");
+    iAdvertiser->UpdateAvailabilityL( ETrue );
+
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::InitTransferData()
+// Initialises the variables needed for progressing and processing the printing
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::InitTransferData()
+{
+    LOG("CBtObjectServer::InitTransferData]\t");
+
+	InitHeaderVariables();
+	iProgress = 0;
+
+	// delete this to be ready to send NULL object.
+    if(iObexBufObject)
+    	delete iObexBufObject;
+    iObexBufObject = NULL;
+
+    // no need to delete. Reset is enough.
+    iObexBody->Reset();
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::InitHeaderVariables()
+// Initialises the variables needed for progressing and processing the printing
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::InitHeaderVariables()
+{
+    LOG("CBtObjectServer::InitHeaderVariables]\t");
+
+	iOffset = 0;
+	iCount = 0; // KErrNotFound indicates "the rest"
+	iSize = KErrNotFound;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::SetSecurityWithChannelL()
+// Sets the security on the channel port and returns the available port.
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::SetSecurityWithChannelL( TBool aAuthentication,
+                                                  TBool aEncryption,
+                                                  TBool aAuthorisation,
+												  TBool aDenied )
+
+{
+
+    LOG("CBtObjectServer::SetSecurityWithChannelL]\t");
+
+	// Local variable to channel to listen to.
+	TInt channel;
+
+	RSocketServ socketServer;
+
+	// Connect to SocetServer
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - connecting to socketServer");
+	User::LeaveIfError( socketServer.Connect() );
+	CleanupClosePushL( socketServer );
+
+	RSocket socket;
+
+	// Open the Socket connection
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - opening a socket");
+	User::LeaveIfError( socket.Open( socketServer, KRFCOMMDesC() ) );
+	CleanupClosePushL( socket );
+
+	// Retreive to one channel that is available.
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - get one channel");
+	User::LeaveIfError( socket.GetOpt( KRFCOMMGetAvailableServerChannel,KSolBtRFCOMM, channel ) );
+
+	// Set the Socket's Port.
+	TBTSockAddr sockaddr;
+	sockaddr.SetPort( channel );
+
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - setting security settings");
+
+	// Set the security according to.
+	TBTServiceSecurity serviceSecurity;
+
+	serviceSecurity.SetUid ( KBtProtocolUid ); // UID for _this_ security service; internal inside the phone
+	serviceSecurity.SetAuthentication ( aAuthentication );
+	serviceSecurity.SetEncryption ( aEncryption );
+	serviceSecurity.SetAuthorisation ( aAuthorisation );
+	serviceSecurity.SetDenied( aDenied );
+
+	// Attach the security settings.
+	sockaddr.SetSecurity(serviceSecurity);
+
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - binding socket to a address");
+
+	// Bind and start listeing the port with security set,
+	User::LeaveIfError(socket.Bind(sockaddr));
+	User::LeaveIfError(socket.Listen(KSimultainousSocketsOpen ) );
+
+	// now close the socket and the socket server
+	CleanupStack::PopAndDestroy(2);  //  socket, socketServer
+
+    LOG("[CBtObjectServer::SetSecurityWithChannelL]\t - returning");
+
+	return channel;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::IsConnected()
+// Results true if the server is connected.
+// ----------------------------------------------------------------------------
+//
+TBool CBtObjectServer::IsConnected()
+{
+    LOG1("CBtObjectServer::IsConnected]\t %d", iConnected);
+    return iConnected;
+}
+
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::IsTransporting()
+// Results true if the transport connection is up.
+// ----------------------------------------------------------------------------
+//
+TBool CBtObjectServer::IsTransporting()
+{
+    LOG1("CBtObjectServer::IsTransporting]\t %d", iTransportUp);
+    return iTransportUp;
+}
+// ----------------------------------------------------------------------------
+// IsSendingData()
+// @return ETrue if the server is sending data to a Bluetooth device
+// ----------------------------------------------------------------------------
+TBool CBtObjectServer::IsSendingData()
+{
+    LOG("CBtObjectServer::IsSendingData]\t");
+
+	if(ESending == iOperation)
+		return ETrue;
+	
+	return EFalse;
+}
+
+// ----------------------------------------------------------------------------
+// IsSendingData()
+// @return ETrue if the server is finished and can be deleted
+// ----------------------------------------------------------------------------
+TBool CBtObjectServer::IsFinished()
+{
+    LOG("CBtObjectServer::IsFinished]\t");
+
+	if(ESending != iOperation)
+		return ETrue;
+	
+	return EFalse;
+}
+
+/*****************************************************************************/
+/* Following methods implement the Obex Observer callbacks in this class     */
+/*****************************************************************************/
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::ErrorIndication()
+// Receive error indication.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::ErrorIndication( TInt aError )
+{
+    LOG2("CBtObjectServer::ErrorIndication]\t iOperation: %d, aError: %d", iOperation, aError);
+    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerError, aError);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::TransportUpIndication()
+// Called when the underlying socket transport connection is made from
+// a remote client to the server
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::TransportUpIndication()
+{
+    LOG1("CBtObjectServer::TransportUpIndication]\t iOperation: %d", iOperation);
+
+	iTransportUp = ETrue;
+
+    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerTransportUp);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::TransportDownIndication()
+// Transport connection is dropped.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::TransportDownIndication()
+{
+    LOG1("[CBtObjectServer::TransportDownIndication]\t iOperation: %d", iOperation);
+
+	iTransportUp = EFalse;
+	
+	if(ETerminating != iOperation)
+		iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerTransportDown);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::ObexConnectIndication()
+// Invoked when an OBEX connection is made from a remote client.
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::ObexConnectIndication(
+    const TObexConnectInfo& /*aRemoteInfo*/, const TDesC8& /*aInfo*/ )
+{
+    LOG("CBtObjectServer::ObexConnectIndication]\t");
+
+	TInt message = KErrAccessDenied;
+
+    /* Check the address of the remote device */
+    if(AllowConnection())
+    {
+    	message = KErrNone;
+    	iConnected = ETrue;
+	    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerConnected);
+    }
+
+    LOG1("CBtObjectServer::ObexConnectIndication]\t returns %d", message);
+	return message;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::ObexDisconnectIndication()
+// OBEX server has been disconnected.
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::ObexDisconnectIndication( const TDesC8& /*aInfo*/ )
+{
+    LOG("CBtObjectServer::ObexDisconnectIndication]\t");
+
+	if(ETerminating != iOperation)
+	{
+	    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerDisconnected);
+	}
+   	iConnected = EFalse;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::PutRequestIndication()
+// ----------------------------------------------------------------------------
+//
+CObexBufObject* CBtObjectServer::PutRequestIndication()
+{
+    LOG("CBtObjectServer::PutRequestIndication]\t");
+
+    /* This is the object where server receives the client request over OBEX */
+    return iObexBufObject;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::PutPacketIndication()
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::PutPacketIndication()
+{
+    LOG("CBtObjectServer::PutPacketIndication]\t");
+
+    return KErrNone;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::PutCompleteIndication()
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::PutCompleteIndication()
+{
+    LOG("CBtObjectServer::PutCompleteIndication]\t");
+
+    return KErrNone;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::GetRequestIndication()
+// Called when a full get request has been received from the client.
+// ----------------------------------------------------------------------------
+//
+CObexBufObject* CBtObjectServer::GetRequestIndication( CObexBaseObject* aRequestedObject )
+{
+    LOG("[CBtObjectServer::GetRequestIndication]\t");
+
+	CObexBufObject* object = NULL;
+
+    /* Check if connection allowed for the remote device */
+    if(AllowConnection())
+    {
+	    iOperation = ESending;
+	    TRAPD(leave, object = HandleGetRequestL(aRequestedObject));
+        if(KErrNone != leave)
+		    LOG1("[CBtObjectServer::GetRequestIndication]\t HandleGetRequestL leaves with %d", leave );
+
+		// Stop advertising if still advertisig...
+        TRAP(leave, iAdvertiser->StopAdvertisingL());
+        if(KErrNone != leave)
+	    	LOG1("[CBtObjectServer::GetRequestIndication]\t StopAdvertisingL leaves with %d", leave);
+    }
+
+    LOG1("[CBtObjectServer::GetRequestIndication]\t return object pointer %d", object );
+    return object;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::GetPacketIndication()
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::GetPacketIndication()
+{
+    LOG("[CBtObjectServer::GetPacketIndication]\t");
+
+    /* Setting that we are now sending data */
+    iOperation = ESending;
+
+    return KErrNone;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::GetCompleteIndication()
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::GetCompleteIndication()
+{
+    LOG("[CBtObjectServer::GetCompleteIndication]\t");
+
+    if(iProgress >= 100)
+        // Sending status that the whole file sent to BT-device 
+	    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerFileSent, iProgress);
+	else
+	    // Sending status that one package sent to BT-device 
+	    iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerPackageSent, iProgress);
+
+    // We are finished for one package - init
+    SetCompleted();
+
+    return KErrNone;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::SetPathIndication()
+// ----------------------------------------------------------------------------
+//
+TInt CBtObjectServer::SetPathIndication( const CObex::TSetPathInfo& /*aPathInfo*/,
+                                         const TDesC8& /*aInfo*/ )
+{
+    LOG("CBtObjectServer::SetPathIndication]\t");
+    return KErrNone;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::AbortIndication()
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::AbortIndication()
+{
+    LOG("CBtObjectServer::AbortIndication]\t");
+
+    SetCompleted();
+
+    /* Sending status that one file sent to BT-device */
+    iObs.HandleObjectServerEvent(KErrAbort);
+
+}
+
+/*****************************************************************************/
+/* Own privates	*/
+/*****************************************************************************/
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::AllowConnection()
+// Checks if the connection should allow.
+// ----------------------------------------------------------------------------
+//
+TBool CBtObjectServer::AllowConnection()
+{
+    LOG("CBtObjectServer::AllowConnection]\t");
+
+    // Return immediatedly if addresses macth
+    if( iRemoteAddress != 0 && iRemoteAddress == iAllowedAddress)
+    	return ETrue;
+    
+    TBool allow = EFalse;
+
+    if( iRemoteAddress == 0 ) 
+    {
+	    /* Getting address of the remote device */
+	    TBTSockAddr remoteAddress;
+	    iObexServer->RemoteAddr(remoteAddress);
+
+	    /* Getting the actual bluetooth address */
+	    iRemoteAddress = remoteAddress.BTAddr();
+
+	    /* Comparing the two bluetooth device addresses */
+	    allow = (iRemoteAddress == iAllowedAddress);
+
+#ifdef _DEBUG
+
+	    TBuf<100> origName;
+	    iAllowedAddress.GetReadable(origName);
+	    TBuf<100> remoteName;
+	    iRemoteAddress.GetReadable(remoteName);
+
+		LOG1("[CBtObjectServer::AllowConnection]\t btAddressOrig: %S", &origName);
+	    LOG1("[CBtObjectServer::AllowConnection]\t btAddressRemote: %S", &remoteName);
+#endif
+    }
+    
+
+    if (!allow)
+    {
+	    LOG("[CBtObjectServer::AllowConnection]\t BT addresses DON'T match!");
+        iObs.HandleObjectServerEvent(MBtObjectServerObserver::KObjectServerBTDeviceMismatch);
+    }
+	else
+	{
+	    LOG("[CBtObjectServer::AllowConnection]\t BT addresses match!");
+	}
+
+	return allow;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::HandleGetRequestL()
+// Called when a full get request has been received from the client.
+// ----------------------------------------------------------------------------
+//
+CObexBufObject* CBtObjectServer::HandleGetRequestL( CObexBaseObject* aRequestedObject )
+{
+	User::LeaveIfNull(aRequestedObject);
+    
+    TFileName name(aRequestedObject->Name());
+
+	TFileName log;
+	CImageInfo::UriLog(name, log);
+    LOG1("[CBtObjectServer::HandleGetRequestL]\t file requested: \"%S\"", &log);
+
+	/* get application parameters header */
+    GetAppHeaderL(aRequestedObject);
+
+	//Append obex header start in uri
+	_LIT(KObex, "obex:");
+	_LIT(KSlash, "/");
+	TFileName scheme(KObex());
+	// Note here: the correct format would be uuid.LongForm(), 
+	// but in currently supported services it is not required.
+	scheme.AppendNum(KBTSDPDPROService, EHex);
+	scheme.Append(KSlash());
+	
+	TInt pos = name.Find(scheme);
+	if(KErrNotFound == pos)
+		name.Insert(0, scheme);
+
+    return CreateObexObjectL(name);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::GetAppHeaderL()
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::GetAppHeaderL(CObexBaseObject* aRequestedObject)
+{
+    LOG("CBtObjectServer::GetAppHeaderL]\t");
+
+	/* get header parameters */
+	InitHeaderVariables();
+
+	TInt indx = 0; // grows cumulatively during GetTriplet
+	TInt tmp = 0;
+
+	// offset
+	TUint tag = 0;
+	TInt len = KBtTripletLength;
+	HBufC8* params = (aRequestedObject->AppParam()).AllocLC();
+
+	if(len <= params->Des().Length())
+	{
+		tmp = TBtMapper::TripletValue(params->Des(), indx, tag);
+	}
+	if(KBtObexTagOffset == tag)
+		iOffset = tmp;
+
+    LOG1("CBtObjectServer::GetAppHeaderL]\t offset: %d", iOffset);
+
+	// count
+	tag = 0;
+	len += KBtTripletLength;
+	if(len <= params->Des().Length())
+	{
+		tmp = TBtMapper::TripletValue(params->Des(), indx, tag);
+	}
+	if(KBtObexTagCount == tag)
+		iCount = tmp;
+
+    LOG1("CBtObjectServer::GetAppHeaderL]\t count: %d", iCount);
+
+	// size
+	tag = 0;
+	len += KBtTripletLength;
+	if(len <= params->Des().Length())
+	{
+		tmp = TBtMapper::TripletValue(params->Des(), indx, tag);
+	}
+	if(KBtObexTagSize == tag)
+		iSize = tmp;
+
+    LOG1("CBtObjectServer::GetAppHeaderL]\t size: %d", iSize);
+
+	CleanupStack::PopAndDestroy(params);
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer
+//
+// ----------------------------------------------------------------------------
+CObexBufObject* CBtObjectServer::CreateObexObjectL(const TDesC& aUri)
+{
+	TFileName log;
+	CImageInfo::UriLog(aUri, log);
+    LOG1("[CBtObjectServer::CreateObexObjectL]\t file requested: \"%S\"", &log);
+    
+    if(iObexBufObject)
+    	delete iObexBufObject;
+    iObexBufObject = NULL;
+
+	TInt size = KErrNotFound;
+
+	for(TInt i = 0; i < iImgArray.Count(); ++i)
+	{
+		if(iImgArray[i].CompareUri(aUri))
+		{
+			TFileName file;
+			iImgArray[i].GetFilePathL(file);
+	    	LOG1("[CBtObjectServer::CreateObexObject]\t file = \"%S\"", &file );
+
+			GetDataSequenceL(file, size);
+		    LOG2("[CBtObjectServer::CreateObexObject]\t data len: %d, file size: %d", iObexBody->Size(), size);
+			if(iObexBody)
+				iObexBufObject = CObexBufObject::NewL(iObexBody);
+
+			break;
+		}
+	}
+    if(!iObexBufObject)
+    {
+	    LOG1("[CBtObjectServer::CreateObexObject]\t return NULL: %d", iObexBufObject);
+    	return iObexBufObject;
+    }
+
+    // Fill headers
+	// File size (application parameters)
+
+	TBuf8<20> triplet;
+
+	triplet.Zero();
+	triplet.Append((TChar)KBtObexTagSize);
+	triplet.Append((TChar)KBtDataLength4);
+	//append value
+	triplet.Append((TChar) ((size & 0xFF000000) >> 24) );
+	triplet.Append((TChar) ((size & 0xFF0000) >> 16) );
+	triplet.Append((TChar) ((size & 0xFF00) >> 8) );
+	triplet.Append((TChar) (size & 0xFF) );
+	triplet.ZeroTerminate();
+
+	iObexBufObject->SetAppParamL(triplet);
+
+   	return iObexBufObject;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::GetDataSequenceL()
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::GetDataSequenceL(const TFileName& aFileName, TInt& aFileSize)
+{
+    //LOG1("[CBtObjectServer::GetDataSequenceL]\t for file \"%S\"", aFileName);
+
+	RFile file;
+	CleanupClosePushL(file);
+	TInt err = file.Open(iFs, aFileName, EFileRead|EFileShareReadersOnly);
+	if(KErrNone != err)
+		User::LeaveIfError(file.Open(iFs, aFileName, EFileRead|EFileShareAny));
+
+	// Get file size
+	aFileSize = KErrNotFound;
+	file.Size(aFileSize);
+    
+	if(!iObexBody)
+	{
+		iObexBody = static_cast<CBufFlat*>(User::LeaveIfNull(CBufFlat::NewL(8)));
+	}
+	iObexBody->Reset();
+
+	// if iCount is zero, return empty body...
+	if(0 == iCount)
+		return;
+
+	// count to send
+	TInt len = iCount;
+
+	// ...if iCount is -1, return the rest of the file
+	// (http://www.bluetooth.com/NR/rdonlyres/276DE16A-BDB9-48BF-8123-AF01E3730E5F/925/BPP_SPEC_V10.pdf)
+	if(KErrNotFound == len)
+	{
+		len = aFileSize - iOffset;
+	}
+    //LOG2("[CBtObjectServer::GetDataSequenceL]\t iOffset: %d, len: %d", iOffset, len);
+
+	HBufC8* data = static_cast<HBufC8*>(User::LeaveIfNull(HBufC8::NewLC(len)));
+	TPtr8 dataPtr( data->Des() );
+
+	dataPtr.Zero();
+	User::LeaveIfError( file.Read(iOffset, dataPtr, len) );
+    //LOG1("[CBtObjectServer::GetDataSequenceL]\t read data->Des().Length(): %d", data->Des().Length());
+
+	iObexBody->InsertL(0, data->Des());
+
+	CleanupStack::PopAndDestroy(2); // data, file
+	
+	//count proggress of this file
+	if(!iOffset)
+		iProgress = iOffset;
+	else
+		iProgress = (((iOffset << 8) / aFileSize) * 100) >> 8;
+	
+    LOG1("[CBtObjectServer::GetDataSequenceL]\t Progress: %d", iProgress);
+	return;
+}
+
+// ----------------------------------------------------------------------------
+// CBtObjectServer::SetCompleted()
+// ----------------------------------------------------------------------------
+//
+void CBtObjectServer::SetCompleted()
+{
+    // method to indicate a package is sent
+    LOG("[CBtObjectServer::SetCompleted]\t");
+
+	// init requested parameters
+	InitTransferData();
+
+    /* If the user of the server called Cancel() */
+    if(ETerminating == iOperation)
+    {
+	    LOG("[CBtObjectServer::SetCompleted]\t to stop...");
+    	Stop();
+    }
+    else
+    {
+	    LOG("[CBtObjectServer::SetCompleted]\t package sent...");
+    	iOperation = EIdle;
+    }
+
+	return;
+}
+
+//  End of File