localconnectivityservice/obexserviceman/obexservicemanserver/src/SrcsSession.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:40 +0100
branchRCL_3
changeset 40 52a167391590
parent 0 c3e98f10fcf4
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2002-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:  SRCS session handler. Dispatchs requests from
*                clients and serves them.
*
*/



// INCLUDE FILES

#include "SrcsSession.h"
#include "obexsm.h"
#include "SrcsMessage.h"
#include "debug.h"
#include <btfeaturescfg.h>


// CONSTANTS

// The granularity of the array used to hold CSrcsMessage objects
static const TInt KMessageArrayGranularity = 4;



// ================= MEMBER FUNCTIONS =======================

// ---------------------------------------------------------
// C++ default constructor can NOT contain any code, that
// might leave.
// constructor - must pass client to CSession2
// ---------------------------------------------------------
//
CSrcsSession::CSrcsSession(CObexSM* aServer) : CSession2(),
                                            iServer(aServer),
                                            iCanceling(EFalse)
    {
    if(iServer)
        {    
        iServer->IncSessionCount();
        }
    }
// ---------------------------------------------------------
// destructor
// ---------------------------------------------------------
//
CSrcsSession::~CSrcsSession()
    {
    FLOG(_L("[SRCS]\tserver\tCSrcsSession closed."));
    if ( iMessageArray )
        {
        // Cleanup the array
        iMessageArray->ResetAndDestroy();
        }
    delete iMessageArray;
    if(iServer)
        {    
        iServer->DecSessionCount();
        } 
    }
// ---------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------
//
CSrcsSession* CSrcsSession::NewL(CObexSM* aServer)
    {
    return new(ELeave) CSrcsSession(aServer);
    }

// ---------------------------------------------------------
// Server
// Return a reference to CSrcs
// ---------------------------------------------------------
CObexSM& CSrcsSession::Server()
    {
    return *iServer;
    }

// ---------------------------------------------------------
// CreateL
// 2nd phase construct for sessions
// - called by the CServer framework
// ---------------------------------------------------------
void CSrcsSession::CreateL()
    {
    // Add session to server first.
    // If anything leaves, it will be removed by the destructor
    ConstructL();
    }

// ---------------------------------------------------------
// ConstructL
// 2nd phase construct for sessions
// - called by the CServer framework
//
// ---------------------------------------------------------
void CSrcsSession::ConstructL()
    {
    iMessageArray = new(ELeave) CArrayPtrFlat<CSrcsMessage>(KMessageArrayGranularity);
    }

// ---------------------------------------------------------
// HandleError
// Handle an error from ServiceL()
// A bad descriptor error implies a badly programmed client, so panic it;
// otherwise report the error to the client
//
// ---------------------------------------------------------
void CSrcsSession::HandleError(TInt aError, const RMessage2& aMessage)
    {
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession::HandleError(): %d"), aError));
    if (aError==KErrBadDescriptor)
        {
        PanicClient( aMessage, ESrcsBadDescriptor);
        }
    else
        {
        CompleteMessage( aMessage, aError);
        }
    }


// ---------------------------------------------------------
// ServiceL
// Calls DispatchMessage under trap harness
//
// ---------------------------------------------------------
void CSrcsSession::ServiceL(const RMessage2& aMessage)
    {
    // First make our own message from RMessage2
    // TRAP because message needs to be completed
    // in case of Leave.        
    TRAPD( err, CreateSrcsMessageL( aMessage ));
    if ( err )
        {
        FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: ServiceL. Error %d when creating message."), err));
        aMessage.Complete( err );
        }
    else
        {
        err = KErrNone;
        TRAP( err ,DispatchMessageL( aMessage ));

        // If we have an error, try to handle it with handle-error.
        if ( err )
            {
            HandleError( err, aMessage );
            }
        }
    }

// ---------------------------------------------------------
// CreateSrcsMessageL
// Creates a CSrcsMessage and appends it to iMessageArray.
// ---------------------------------------------------------
//
void CSrcsSession::CreateSrcsMessageL(const RMessage2& aMessage)
    {
    __ASSERT_DEBUG(iMessageArray!=NULL, PanicServer(ESrcsClassMemberVariableIsNull));
    CSrcsMessage* message = CSrcsMessage::NewL(aMessage);
    CleanupStack::PushL( message );
    iMessageArray->AppendL( message );
    CleanupStack::Pop();
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: MessageArray count: %d"), iMessageArray->Count()));
    }

// ---------------------------------------------------------
// CompleteMessage
// Finds a message based on aMessage and completes it.
// ---------------------------------------------------------
//
void CSrcsSession::CompleteMessage(const RMessage2& aMessage, TInt aReason)
    {
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteMessage."));
    CSrcsMessage* message = FindMessage(aMessage);
    __ASSERT_DEBUG(message!=NULL, PanicServer(ESrcsBadMessage));
    message->Complete(aReason);
    DeleteMessage( message );
    }

// ---------------------------------------------------------
// CompleteMessage
// Completes given message.
// ---------------------------------------------------------
//
void CSrcsSession::CompleteMessage(CSrcsMessage* aMessage, TInt aReason)
    {
    __ASSERT_DEBUG(aMessage!=NULL, PanicServer(ESrcsBadMessage));
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteMessage."));
    aMessage->Complete(aReason);
    DeleteMessage(aMessage);
    }

// ---------------------------------------------------------
// CompletePendingMessages
// Completes any messages pending in the CBTManMessage array.
// ---------------------------------------------------------
void CSrcsSession::CompletePendingMessages()
    {
    __ASSERT_DEBUG(iMessageArray!=NULL, PanicServer(ESrcsClassMemberVariableIsNull));
    CSrcsMessage* messagePtr = NULL;
    TInt count = iMessageArray->Count();
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession::CompletePendingMessages. Message count: %d"), count));

    // Messages can be completed from array
    // and deleted after that.
    for ( TInt index = ( count-1 ) ; index >= 0 ; index-- )
        {
        messagePtr = iMessageArray->At(index);
        messagePtr->Complete(KErrDied);
        iMessageArray->Delete(index);
        delete messagePtr;
        messagePtr = NULL;
        }
    }

// ---------------------------------------------------------
// FindMessage
// Searches the array of CBTManMessages for the one dealing with aMessage.
// ---------------------------------------------------------
//
CSrcsMessage* CSrcsSession::FindMessage(const RMessage2& aMessage)
    {
    __ASSERT_DEBUG(iMessageArray!=NULL, PanicServer(ESrcsClassMemberVariableIsNull));
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: FindMessage."));
    RMessagePtr2 messagePtr = aMessage;
    CSrcsMessage* ptr = NULL;

    for ( TInt index = 0 ; index < iMessageArray->Count() ; index++ )
        {
        ptr = iMessageArray->At( index );
        if( ptr->MessagePtr() == messagePtr )
            {
            FLOG(_L("[SRCS]\tserver\tCSrcsSession: FindMessage. Message found"));
            return ptr;
            }
        }
    return NULL;
    }

// ---------------------------------------------------------
// FindMessage
// Searches the array for the 1st message with the function.
// ---------------------------------------------------------
//
CSrcsMessage* CSrcsSession::FindMessage(TInt aFunction)
    {
    __ASSERT_DEBUG(iMessageArray!=NULL, PanicServer(ESrcsClassMemberVariableIsNull));
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: FindMessage aFunction %d"), aFunction));
    CSrcsMessage* ptr = NULL;
    for ( TInt index = 0 ; index < iMessageArray->Count() ; index++ )
        {
        ptr = iMessageArray->At( index );
        if ( ptr->MessagePtr().Function() == aFunction )
            {
            FLOG(_L("[SRCS]\tserver\tCSrcsSession: FindMessage. Message found"));
            return ptr;
            }
        }
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: FindMessage. Message not found"));
    return NULL;
    }

// ---------------------------------------------------------
// DeleteMessage
// Find the CSrcsMessage in the message array and delete it.
// ---------------------------------------------------------
//
void CSrcsSession::DeleteMessage(CSrcsMessage* aMessage)
    {
    __ASSERT_DEBUG(iMessageArray!=NULL, PanicServer(ESrcsClassMemberVariableIsNull));
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: DeleteMessage. "));
    CSrcsMessage* ptr = NULL;
    TInt count = iMessageArray->Count();
    for ( TInt index = ( count-1 ) ; index >= 0 ; index-- )
        {
        ptr = iMessageArray->At( index );
        if( ptr == aMessage )
            {
            FLOG(_L("[SRCS]\tserver\tCSrcsSession: Message deleting. "));
            //Delete the message first before removing from the array since a helper associated
            //with the message will try to find the message by parsing the array as part of the
            //destruction the message.
            delete ptr;
            iMessageArray->Delete( index );
            ptr = NULL;
            break;
            }
        }
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: MessageArray count: %d"), iMessageArray->Count()));
    //compress the array if the count is less than the length - granularity AND if the count != 0
    if ( iMessageArray->Count() )
        {
        if (iMessageArray->Length() - iMessageArray->Count() >= KMessageArrayGranularity)
            iMessageArray->Compress();
        }
    }


// ---------------------------------------------------------
// DispatchMessageL
// service a client request; test the opcode and then do
// appropriate servicing
// ---------------------------------------------------------
//
void CSrcsSession::DispatchMessageL(const RMessage2 &aMessage)
    {
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: DispatchMessageL function %d"), aMessage.Function()));
    iCanceling=EFalse;
    switch (aMessage.Function())
        {
        // Turn BT services ON (with service handler).
    case ESrcsBTServicesON:
            {
			if ( BluetoothFeatures::EnterpriseEnablementL() != BluetoothFeatures::EEnabled )
				{
				CompleteMessage(aMessage, KErrNotSupported);
				}
			else
				{			
	            ManageServices(ESrcsTransportBT, ETrue, aMessage);
				}
            break;
            }
        // Turn BT services OFF.
    case ESrcsBTServicesOFF:
            {
            ManageServices(ESrcsTransportBT, EFalse, aMessage);
            break;
            }

        // Turn IrDA services ON (with service handler).
    case ESrcsIrDAServicesON:
            {
            ManageServices(ESrcsTransportIrDA, ETrue, aMessage);
            break;
            }
        // Turn IrDA services OFF.
    case ESrcsIrDAServicesOFF:
            {
            ManageServices(ESrcsTransportIrDA, EFalse, aMessage);
            break;
            }

    case ESrcsStartUSB:
            {
            ManageServices(ESrcsTransportUSB, ETrue, aMessage);
            break;
            }
    case ESrcsStopUSB:
            {
            ManageServices(ESrcsTransportUSB, EFalse, aMessage);
            break;
            }    
     case ESrcsCancelRequest:
            {            
            FLOG(_L("[SRCS]\tserver\tCSrcsSession: DispatchMessageL: ESrcsCancelRequest"));
            CancelingRequest(aMessage);
            break;
            }
    default:
            {
            PanicClient( aMessage, ESrcsBadRequest);
            break;
            }
        }
    }

// ---------------------------------------------------------
// ManageServicesL
// OpCode function; Manages Services.
// ---------------------------------------------------------
//
void CSrcsSession::ManageServices(TSrcsTransport aTransport, TBool aState, 
                                  const RMessage2& aMessage)
    {
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: ManageServicesL"));
    TInt retVal = Server().ManageServices(aTransport, aState, this, aMessage);
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: ManageServicesL return %d"), retVal));
    }

// ---------------------------------------------------------
// CancelingRequest
// Canceling the ongoing request.
// ---------------------------------------------------------
//
void CSrcsSession::CancelingRequest(const RMessage2& aMessage)
    {
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: CancelingRequest"));
    iCanceling=ETrue;          
    if (iMessageArray->Count() == 1)
        {
        FLOG(_L("[SRCS]\tserver\tCSrcsSession: CancelingRequest completing"));
        CompleteMessage(aMessage, KErrGeneral);        
        }
    else
        {
        //The cancel handling continues, when another request completes.
        }
    }
    
// ---------------------------------------------------------
// RequestCompleted
// ---------------------------------------------------------
//   
void CSrcsSession::RequestCompleted(const RMessage2 &aMessage, TInt aError)
    {          
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: RequestCompleted"));
    TBool postponeCompletion = EFalse;
    if ( !iCanceling )
        {
        FLOG(_L("[SRCS]\tserver\tCSrcsSession: RequestCompleted completing"));
        CompleteMessage( aMessage, aError ); 
        }
    else
        {
        CompleteCanceling(aMessage, aError, postponeCompletion);
        }
    if ( !postponeCompletion && iMessageArray->Count() > 0 )
        {
        FLOG(_L("[SRCS]\tserver\tCSrcsSession: RequestCompleted dispatching"));
        CSrcsMessage* messagePtr = NULL; 
        messagePtr=iMessageArray->At( 0 ); 
        RMessage2 message=messagePtr->MessagePtr(); 
        TRAP_IGNORE( DispatchMessageL( message ) );
        }    
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: RequestCompleted exit"));
    }

// ---------------------------------------------------------
// CompleteCanceling
// Only USB service cancel is handled, since Locod Service 
// Plugin API does not allow cancel for BT or IrDA.
// ---------------------------------------------------------
//
void CSrcsSession::CompleteCanceling(const RMessage2& aMessage, TInt aError, 
                                     TBool& aPostponeCompletion)
    {          
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling"));
    TBool cancelMsgFound = EFalse;
    CSrcsMessage* messagePtr = NULL;
    FTRACE(FPrint(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling function %d"), 
        aMessage.Function()));
    switch ( aMessage.Function() )
        {    
        case ESrcsStartUSB:
            messagePtr = FindMessage(ESrcsCancelRequest);
            if ( messagePtr )
                {
                FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling ESrcsStartUSB found cancel req"));
                RMessage2 message=messagePtr->MessagePtr();                
                ManageServices(ESrcsTransportUSB, EFalse,  message);
                aPostponeCompletion = ETrue;
                cancelMsgFound = ETrue;
                }
            break;
        case ESrcsStopUSB:
            messagePtr = FindMessage(ESrcsCancelRequest);
            if ( messagePtr )
                {
                CompleteMessage(aMessage, KErrCancel); 
                CompleteMessage(messagePtr, aError); 
                cancelMsgFound = ETrue;
                }
            break;
        case ESrcsCancelRequest:
            //either start or stop USB
            messagePtr = FindMessage(ESrcsStartUSB);
            if ( !messagePtr )
                {
                messagePtr = FindMessage(ESrcsStopUSB);
                }
            if ( messagePtr )
                {
                CompleteMessage(messagePtr, KErrCancel); 
                CompleteMessage(aMessage, aError);
                cancelMsgFound = ETrue;
                }
            break;
        default:
            FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling ESrcsCancelRequest unhandled msg"));
            break;
        }
    if ( !cancelMsgFound )
        {
        FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling no message"));
        CompleteMessage(aMessage, KErrGeneral);
        }
    FLOG(_L("[SRCS]\tserver\tCSrcsSession: CompleteCanceling exit"));    
    }
// End of File