diff -r 000000000000 -r a4daefaec16c sipvoipprovider/svptransfer/src/svptransfercontroller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sipvoipprovider/svptransfer/src/svptransfercontroller.cpp Mon Jan 18 20:12:36 2010 +0200 @@ -0,0 +1,803 @@ +/* +* Copyright (c) 2006 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: Transfer controller class, transfer is controlled through +* this class +* +*/ + +#include // CMceInRefer +#include // CMceEvent, CMceInEvent +#include // TMceTransactionDataContainer + +#include "svptransfercontroller.h" +#include "svptransferstatecontext.h" +#include "svplogger.h" +#include "svpsessionbase.h" // CSVPSessionBase +#include "svpsipconsts.h" +#include "svpconsts.h" + +// --------------------------------------------------------------------------- +// CSVPTransferController::CSVPTransferController +// --------------------------------------------------------------------------- +// +CSVPTransferController::CSVPTransferController() : + iTransferContext (NULL), + iCCPTransferObserver (NULL), + iAccepted( EFalse ) + { + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::ConstructL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::ConstructL( + CMceSession* aMceSession, + CSVPSessionBase* aSVPSession, + TMceTransactionDataContainer& aContainer, + MSVPTransferObserver& aObserver ) + { + // Transfer state context + iTransferContext = CSVPTransferStateContext::NewL( + aMceSession, aSVPSession, + aContainer, aObserver ); + } + + +// --------------------------------------------------------------------------- +// CSVPTransferController::NewL +// --------------------------------------------------------------------------- +// +CSVPTransferController* CSVPTransferController::NewL( + CMceSession* aMceSession, + CSVPSessionBase* aSVPSession, + TMceTransactionDataContainer& aContainer, + MSVPTransferObserver& aObserver ) + { + CSVPTransferController* self = CSVPTransferController::NewLC( + aMceSession, + aSVPSession, + aContainer, + aObserver ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// CSVPTransferController::NewLC +// --------------------------------------------------------------------------- +// +CSVPTransferController* CSVPTransferController::NewLC( + CMceSession* aMceSession, + CSVPSessionBase* aSVPSession, + TMceTransactionDataContainer& aContainer, + MSVPTransferObserver& aObserver ) + { + CSVPTransferController* self = new( ELeave ) CSVPTransferController; + CleanupStack::PushL( self ); + self->ConstructL( aMceSession, aSVPSession, aContainer, aObserver ); + return self; + } + + +// --------------------------------------------------------------------------- +// CSVPTransferController::~CSVPTransferController +// --------------------------------------------------------------------------- +// +CSVPTransferController::~CSVPTransferController() + { + delete iTransferContext; + } + + +// --------------------------------------------------------------------------- +// Handle mce event observer notify events. +// The state of the event has changed. +// --------------------------------------------------------------------------- +// +void CSVPTransferController::HandleEventStateChangedL( + CMceEvent& /* aEvent */, + TInt aStatusCode ) + { + if ( KSVPOKVal == aStatusCode ) + { + if ( iTransferContext->IsAttended() ) + { + SVPDEBUG1( "CSVPTransferController::HandleEventStateChangedL: KSVPOKVal & attended" ); + if ( KSVPTransferAcceptedStateIndex == iTransferContext->CurrentState()) + { + // F25 OK received - already acccepted + // leave for not to create new session later + SVPDEBUG1( "CSVPTransferController::HandleEventStateChangedL: transfer in progress"); + User::Leave( KSVPErrTransferInProgress ); + } + + // F18 OK received as response for "trying" + // Set and apply the next state - accepted + iTransferContext->SetCurrentStateL( KSVPTransferAcceptedStateIndex ); + iTransferContext->ApplyCurrentStateL(); + SVPDEBUG1( "CSVPTransferController::HandleEventStateChangedL:ApplyCurrentStateL done" ); + } + else // unattended transfer + { + SVPDEBUG1( "CSVPTransferController::HandleEventStateChangedL: KSVPOKVal unattended" ); + if ( iTransferContext->CheckIsSessionRemoteHold() && + KSVPTransferAcceptedStateIndex == iTransferContext->CurrentState() ) + { + // Transferer has put transferee on hold before sending refer + SVPDEBUG1( "CSVPTransferController::HandleEventStateChangedL: Snom or similar as transferer" ); + SendNotifyL( aStatusCode ); // 200 OK + } + } + } + else + { + SVPDEBUG2("CSVPTransferController::HandleEventStateChangedL: aStatusCode = %d", + aStatusCode); + } + SVPDEBUG1("CSVPTransferController::HandleEventStateChangedL: Out"); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::NotifyReceivedL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::NotifyReceivedL( + CMceEvent& aEvent, + TMceTransactionDataContainer* aContainer ) + { + SVPDEBUG1("CSVPTransferController::NotifyReceivedL: In"); + + // check data container and match the event to the active refer event + if ( aContainer && iTransferContext->MceEvent() == &aEvent ) + { + TInt statusCode = aContainer->GetStatusCode(); + HBufC8* content = aContainer->GetContent(); + + SVPDEBUG2( "CSVPTransferController::NotifyReceivedL:\ + statusCode: %d", statusCode ); + SVPDEBUG2( "CSVPTransferController::NotifyReceivedL:\ + aContainer->GetContent()->Length(): %d", content->Length() ); + + if ( !content->Find( TPtrC8( KSVPNotifyTrying ) ) ) + { + if ( iTransferContext->IsAttended() ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, Attended case:\ + SIP/2.0 100 Trying" ); + + // Attended transfer (F17) NOTIFY , transferee is trying establish new session. + // Check if 202 Accepted already received + if ( iAccepted ) + { + // Stop the refer timer + iTransferContext->StopReferTimer( ); + // Set and apply the next state - accepted + iTransferContext->SetCurrentStateL( + KSVPTransferAcceptedStateIndex ); + iTransferContext->ApplyCurrentStateL(); + } + } + else + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, UnAttended case:\ + SIP/2.0 100 Trying" ); + + // Check if 202 Accepted already received + if ( iAccepted ) + { + // Stop the refer timer + iTransferContext->StopReferTimer( ); + + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, Unattended: is accepted" ); + + // Unattended transfer: F7 NOTIFY, display "transferred" note + if( iCCPTransferObserver ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, send local transfer" ); + iCCPTransferObserver->TransferEventOccurred( + MCCPTransferObserver::ECCPLocalTransfer ); + } + + // Set and apply the next state - accepted + iTransferContext->SetCurrentStateL( + KSVPTransferAcceptedStateIndex ); + iTransferContext->ApplyCurrentStateL(); + + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + // Unattended transfer is ok, hangup the session + iTransferContext->TransferObserver().TransferNotification( + ESVPTransferOKHangUp ); + } + } + } + else if ( !content->Find( TPtrC8( KSVPNotifyOK ) ) ) + { + if ( iTransferContext->IsAttended() ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, Attended case:\ + SIP/2.0 200 OK" ); + + // Attended transfer (F24) 200 OK + if( iCCPTransferObserver ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, send local transfer" ); + iCCPTransferObserver->TransferEventOccurred( + MCCPTransferObserver::ECCPLocalTransfer ); + } + + // Set and apply the next state - terminating + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + + // Attended transfer is ok, hangup the session + iTransferContext->TransferObserver().TransferNotification( + ESVPTransferOKHangUp ); + } + else + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, UnAttended: SIP/2.0 200 OK" ); + } + } + else if ( !content->Find( TPtrC8( KSVPNotifyRinging ) ) && + !iTransferContext->IsAttended()) + { + // Polycom send Ringing instead of Trying in unattended case. + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, UnAttended and 180 Ringing" ); + + // Check if 202 Accepted already received + if ( iAccepted ) + { + // Stop the refer timer + iTransferContext->StopReferTimer( ); + + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, Unattended: Polycom case" ); + + // Unattended transfer: display "transferred" note + if( iCCPTransferObserver ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, send local transfer" ); + iCCPTransferObserver->TransferEventOccurred( + MCCPTransferObserver::ECCPLocalTransfer ); + } + + // Set and apply the next state - accepted + iTransferContext->SetCurrentStateL( + KSVPTransferAcceptedStateIndex ); + iTransferContext->ApplyCurrentStateL(); + + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + // Unattended transfer is ok, hangup the session + iTransferContext->TransferObserver().TransferNotification( + ESVPTransferOKHangUp ); + } + } + else if ( !content->Find( TPtrC8( KSVPNotifyServiceUnavailable ) ) ) + { + // Notify that comes after the accepted refer, if + // the (wrong) address of the refer cannot be reached. + if ( KSVPTransferAcceptedStateIndex == iTransferContext->CurrentState() ) + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, 503 -> ECCPTransferFailed"); + + // Set and apply the next state - terminating + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + + // Transfer fails, notify client. + iTransferContext->TransferObserver().TransferNotification( + ESVPTransferDecline ); + } + else + { + SVPDEBUG1( "CSVPTransferController::NotifyReceivedL, 503."); + } + } + else + { + SVPDEBUG1("CSVPTransferController::NotifyReceivedL:\ + Unhandled container content"); + } + + // Ownership transferred here + delete content; + } + + SVPDEBUG1("CSVPTransferController::NotifyReceivedL: Out"); + } + + +// --------------------------------------------------------------------------- +// CSVPTransferController::HandleReferStateChangeL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::HandleReferStateChangeL( CMceRefer& aRefer, + TInt aStatusCode ) + { + SVPDEBUG1("CSVPTransferController::HandleReferStateChangeL() In"); + + if ( iTransferContext->MceRefer() == &aRefer ) + { + if ( KSVPAcceptedVal == aStatusCode ) + { + // Accepted unattended F6, Attended F16 + SVPDEBUG2( "CSVPTransferController::HandleReferStateChangeL: Accept: %i", + KSVPAcceptedVal ); + + // Display "transferring" note + if( iCCPTransferObserver ) + { + SVPDEBUG1( "CSVPTransferController::HandleReferStateChangeL, send remote transferring" ); + iCCPTransferObserver->TransferEventOccurred( + MCCPTransferObserver::ECCPRemoteTransferring ); + } + // Continue acceptance when also notify F7 / F17 "trying" received + iAccepted = ETrue; + } + else if ( ( KSVPBadRequestVal <= aStatusCode && + KSVPRequestPendingVal >= aStatusCode ) || + KSVPDeclineVal == aStatusCode || + KSVPServerInternalErrorVal == aStatusCode || + KSVPPreconditionFailureVal == aStatusCode ) + { + // Decline, Request Failure 4xx or Server Failure 5xx + SVPDEBUG2( "CSVPTransferController::HandleReferStateChangeL: Code: %i", aStatusCode ); + // Stop the refer timer + iTransferContext->StopReferTimer( ); + + // Set and apply the next state - terminating + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + + // Notify the observer about the decline. + iTransferContext->TransferObserver().TransferNotification( + ESVPTransferDecline ); + } + + else + { + // Not handled + SVPDEBUG2( "CSVPTransferController::HandleReferStateChangeL: \ + Unknown StatusCode: %i", aStatusCode ); + } + } + else + { + // Unknown refer - not handled + SVPDEBUG1( "CSVPTransferController::HandleReferStateChangeL: \ + Unknown refer"); + } + + SVPDEBUG1("CSVPTransferController::HandleReferStateChangeL() Out"); + } + + +// --------------------------------------------------------------------------- +// CSVPTransferController::IncomingReferL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::IncomingReferL( CMceInRefer* aRefer, + const TDesC8& aReferTo, TMceTransactionDataContainer* aContainer ) + { + SVPDEBUG1( "CSVPTransferController::IncomingReferL In" ) + + // Is new incoming refer handling possible + if ( KSVPTransferIdleStateIndex == iTransferContext->CurrentState() ) + { + SVPDEBUG1( "CSVPTransferController::IncomingReferL: allowed" ) + + iTransferContext->SetMceRefer( static_cast( aRefer ) ); + iTransferContext->SetIncomingReferToL( aReferTo ); + CDesC8Array* headers = aContainer->GetHeaders();// get headers + + if ( headers ) + { + TBool found = EFalse; + + for( TInt i = 0; i < headers->MdcaCount() && !found; i++ ) + { + TPtrC8 tmpHeader = headers->MdcaPoint( i ); + + if ( KErrNotFound != tmpHeader.FindF( KSVPReferredBy ) ) + { + SVPDEBUG1( "KSVPReferredBy found" ) + found = ETrue; + iTransferContext->SetIncomingReferredByL( tmpHeader ); + } + } + } + + delete headers; + headers = NULL; + } + else + { + SVPDEBUG1( "CSVPTransferController::IncomingReferL: not allowed" ) + User::Leave( KSVPErrTransferStateError ); + } + + if ( iTransferContext->IsAttended() ) + { + SVPDEBUG1( "CSVPTransferController::IncomingReferL: Attended case, send accept" ) + + // send trying notification and wait respond for it + CMceInEvent* inEvent = NULL; + + TRAPD( acceptError, inEvent = static_cast( + iTransferContext->MceRefer() )->AcceptL() ); + + if ( KErrNone == acceptError ) + { + // Apply state, changes to next state (pending) + SVPDEBUG1( "CSVPTransferController::IncomingReferL: pending state" ) + iTransferContext->SetMceEvent( static_cast( inEvent ) ); + iTransferContext->ApplyCurrentStateL(); + } + else + { + // Set and apply the next state - terminating + SVPDEBUG2("CSVPTransferController::IncomingReferL: acc fails = %d", acceptError ) + iTransferContext->SetCurrentStateL( KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + } + } + else + { + // Apply state, changes to next state (pending) + SVPDEBUG1( "CSVPTransferController::IncomingReferL: UnAttended case pending" ) + iTransferContext->ApplyCurrentStateL(); + } + + SVPDEBUG1( "CSVPTransferController::IncomingReferL Out" ) + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::IsMceRefer +// --------------------------------------------------------------------------- +// +TBool CSVPTransferController::IsMceRefer( CMceRefer& aRefer ) + { + return ( iTransferContext->MceRefer() == &aRefer ); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::IsAttended +// --------------------------------------------------------------------------- +// +TBool CSVPTransferController::IsAttended( ) + { + return ( iTransferContext->IsAttended() ); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::SetTransferDataL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::SetTransferDataL( CDesC8Array* aUserAgentHeaders, + TInt aSecureStatus ) + { + SVPDEBUG1(" CSVPTransferController::SetTransferDataL" ); + iTransferContext->SetTransferDataL( aUserAgentHeaders, aSecureStatus ); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::SetMceSessionObject +// --------------------------------------------------------------------------- +// +void CSVPTransferController::SetMceSessionObject( CMceSession* aSession ) + { + iTransferContext->SetMceSessionObject( aSession ); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::SendNotifyL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::SendNotifyL( TInt aStatusCode ) + { + SVPDEBUG2("CSVPTransferController::SendNotifyL() code = %d", aStatusCode); + + CMceInEvent* inEvent = static_cast< CMceInEvent* > ( + iTransferContext->MceEvent()); + if (inEvent) + { + HBufC8* contentType = KSVPMessageSipfrag().AllocLC(); //message/sipfrag + HBufC8* content = NULL; + + if (KSVPOKVal == aStatusCode ) + { + content = KSVPNotifyOK().AllocLC(); // "SIP/2.0 200 OK" + } + else if ( KSVPNotFoundVal == aStatusCode || + KSVPBusyHereVal == aStatusCode || + KSVPDeclineVal == aStatusCode ) + { + content = KSVPNotifyServiceUnavailable().AllocLC(); // "503" + } + else + { + SVPDEBUG2("CSVPTransferController::SendNotifyL unknown aStatusCode = %d", aStatusCode); + content = KSVPNotifyServiceUnavailable().AllocLC(); // "503" + } + + CDesC8Array* headers = NULL; + headers = new( ELeave ) CDesC8ArrayFlat( KSVPContactArrayGranularity ); + CleanupStack::PushL( headers ); + headers->AppendL( KSVPSubsStateTerminated ); + + // Notify is sent to transferer (unattended msg F15, attended msg F24) + TRAPD( errNotify, inEvent->TerminateL( headers, contentType, content ) ); + + if ( KErrNone == errNotify ) + { + SVPDEBUG1("CSVPTransferController::SendNotifyL, notify sending OK"); + CleanupStack::Pop( 3, contentType ); // headers, content, contentType + } + else + { + // error handling + SVPDEBUG2("CSVPTransferController::SendNotifyL: errNotify = %d", errNotify ); + CleanupStack::PopAndDestroy( 3, contentType ); // headers, content, contentType + } + } + + if ( iTransferContext->IsAttended() ) + { + SVPDEBUG1("CSVPTransferController::SendNotifyL() Attended done"); + } + else + { + SVPDEBUG1("CSVPTransferController::SendNotifyL() UnAttended to terminating state"); + // Finish unattended incoming transfer sequence + // Set and apply the next state - terminating + iTransferContext->SetCurrentStateL( KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + } + + SVPDEBUG1("CSVPTransferController::SendNotifyL() Out"); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::IsIncomingTransfer +// --------------------------------------------------------------------------- +// +TBool CSVPTransferController::IsIncomingTransfer() + { + SVPDEBUG2("CSVPTransferController::IsIncomingTransfer = %d", + iTransferContext->IsIncoming() ); + return iTransferContext->IsIncoming(); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::TerminateTransfer +// --------------------------------------------------------------------------- +// +void CSVPTransferController::TerminateTransfer() + { + SVPDEBUG1("CSVPTransferController::TerminateTransfer" ) + TRAP_IGNORE( TerminateTransferL() ); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::TerminateTransferL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::TerminateTransferL() + { + iTransferContext->SetCurrentStateL( KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::AttendedTransfer +// --------------------------------------------------------------------------- +// +TInt CSVPTransferController::AttendedTransfer( MCCPCall& aTransferTargetCall ) + { + SVPDEBUG1( "CSVPTransferController::AttendedTransfer call IN" ); + TRAPD( transError, TransferL( &aTransferTargetCall, KNullDesC, ETrue )); + SVPDEBUG2( "CSVPTransferController::AttendedTransfer A return: %d", transError ); + return transError; + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::AttendedTransfer +// --------------------------------------------------------------------------- +// +TInt CSVPTransferController::AttendedTransfer( const TDesC& aTransferTarget ) + { + SVPDEBUG1( "CSVPTransferController::AttendedTransfer target IN" ); + TRAPD( transError, TransferL( NULL, aTransferTarget, ETrue )); + SVPDEBUG2( "CSVPTransferController::AttendedTransfer B return: %d", transError ); + return transError; + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::UnattendedTransfer +// --------------------------------------------------------------------------- +// +TInt CSVPTransferController::UnattendedTransfer( const TDesC& aTransferTarget ) + { + SVPDEBUG1( "CSVPTransferController::UnattendedTransfer IN" ); + TRAPD( transError, TransferL( NULL, aTransferTarget, EFalse )); + SVPDEBUG2( "CSVPTransferController::UnattendedTransfer return: %d", transError ); + return transError; + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::AcceptTransfer +// --------------------------------------------------------------------------- +// +TInt CSVPTransferController::AcceptTransfer( const TBool aAccept ) + { + SVPDEBUG2("CSVPTransferController::AcceptTransfer() IN aAccept = \ + %d", aAccept); + TInt acceptError = KErrNone; + TInt stateError = KErrNone; + TInt currentState = iTransferContext->CurrentState(); + CMceInEvent* inEvent(NULL); + + // Is state "pending" + if ( KSVPTransferPendingStateIndex == currentState ) + { + if ( aAccept ) + { + TRAP( acceptError, ( inEvent = static_cast< CMceInRefer* > (iTransferContext->MceRefer())->AcceptL())); + SVPDEBUG2("CSVPTransferController::AcceptTransfer()\ + AcceptL = %d", acceptError); + } + else + { + SVPDEBUG1("CSVPTransferController::AcceptTransfer() reject"); + TRAP( acceptError, ( static_cast< CMceInRefer* > (iTransferContext->MceRefer())->RejectL()) ); + } + + if ( KErrNone == acceptError ) + { + if ( aAccept ) + { + // Set the received event + iTransferContext->SetMceEvent(static_cast< CMceEvent* >(inEvent)); + + // Set and apply the next state - accepted + TRAP( acceptError, + iTransferContext->SetCurrentStateL( + KSVPTransferAcceptedStateIndex ); + iTransferContext->ApplyCurrentStateL(); + ); + } + else + { + // Set and apply the next state - terminating + TRAP( acceptError, + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + ); + } + } + else + { + SVPDEBUG2("CSVPTransferController::AcceptTransfer()\ + fails = %d", acceptError); + // Set and apply the next state - terminating + TRAP( stateError, + iTransferContext->SetCurrentStateL( + KSVPTransferTerminatingStateIndex ); + iTransferContext->ApplyCurrentStateL(); + ); + SVPDEBUG2("CSVPTransferController::AcceptTransfer()\ + stateError = %d", stateError); + } + } + else + { + SVPDEBUG2("CSVPTransferController::AcceptTransfer()\ + current state is not pending: %d", currentState); + acceptError = KSVPErrTransferStateError; + } + + SVPDEBUG2("CSVPTransferController::AcceptTransfer()\ + OUT acceptError = %d", acceptError); + return acceptError; + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::TransferTarget +// --------------------------------------------------------------------------- +// +const TDesC& CSVPTransferController::TransferTarget() const + { + return iTransferContext->IncomingReferTo(); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::AddObserverL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::AddObserverL( + const MCCPTransferObserver& aObserver ) + { + SVPDEBUG1("CSVPTransferController::AddObserverL() In"); + // set transfer observer + // only one observer used at a time, replaces current one + iCCPTransferObserver = const_cast(&aObserver); + + SVPDEBUG1("CSVPTransferController::AddObserverL() Out"); + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::RemoveObserver +// --------------------------------------------------------------------------- +// +TInt CSVPTransferController::RemoveObserver( + const MCCPTransferObserver& aObserver ) + { + SVPDEBUG1("CSVPTransferController::RemoveObserver"); + TInt err = KErrNone; + if ( iCCPTransferObserver == const_cast + (&aObserver) ) + { + iCCPTransferObserver = NULL; + } + else + { + err = KErrNotFound; + } + return err; + } + +// --------------------------------------------------------------------------- +// CSVPTransferController::TransferL +// --------------------------------------------------------------------------- +// +void CSVPTransferController::TransferL( MCCPCall* aCall, + const TDesC& aTarget, + const TBool aAttendedTransfer ) + { + SVPDEBUG1("CSVPTransferController::TransferL() In"); + + // Transfer possible. + if ( KSVPTransferIdleStateIndex == iTransferContext->CurrentState() ) + { + iAccepted = EFalse; + + // Set transfer parameters + iTransferContext->SetTransferParmsL( + static_cast< CSVPSessionBase* >(aCall), + aTarget, + aAttendedTransfer ); + + // Apply state, execute the refer and change to next state (pending). + iTransferContext->ApplyCurrentStateL(); + } + else + { + SVPDEBUG1( "CSVPTransferController::TransferL: Error - transfer in progress" ); + iTransferContext->TransferObserver().TransferFailed( KErrInUse ); + TerminateTransferL(); + } + + SVPDEBUG1("CSVPTransferController::TransferL() OUT"); + } + +