diff -r ccd8e69b5392 -r 496ad160a278 mmsharing/mmshavailability/src/musavaterminal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmsharing/mmshavailability/src/musavaterminal.cpp Fri Jun 11 13:36:18 2010 +0300 @@ -0,0 +1,616 @@ +/* +* Copyright (c) 2005-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: Discovered terminal +* +*/ + + +#include "musavaterminal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "muslogger.h" +#include "musavacapabilityexchange.h" +#include "musavacapability.h" +#include "musavacapabilityquerybase.h" +#include "musavacapabilitycontext.h" +#include "mmusavacapabilityqueryobserver.h" +#include "mussettings.h" +#include "mussettingskeys.h" +#include "musavasipheaderutil.h" + +// -------------------------------------------------------------------------- +// Symbian two-phase constructor +// -------------------------------------------------------------------------- +// +CMusAvaTerminal* CMusAvaTerminal::NewL( CMusAvaCapabilityExchange& aExchange, + const TDesC8& aTerminalUri, + const TDesC8& aTerminalId ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::NewL" ) + CMusAvaTerminal* self = new (ELeave) CMusAvaTerminal( aExchange ); + CleanupStack::PushL( self ); + self->ConstructL( aTerminalUri, aTerminalId ); + CleanupStack::Pop( self ); + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::NewL" ) + return self; + } + + +// -------------------------------------------------------------------------- +// C++ destructor +// -------------------------------------------------------------------------- +// +CMusAvaTerminal::~CMusAvaTerminal() + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::~CMusAvaTerminal" ) + + ResetAndDestroyQuery(); + + delete iUri; + delete iTerminalId; + iRequestedQuery = NULL; + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::~CMusAvaTerminal" ) + } + +// -------------------------------------------------------------------------- +// C++ constructor +// -------------------------------------------------------------------------- +// +CMusAvaTerminal::CMusAvaTerminal( CMusAvaCapabilityExchange& aExchange ) + : iExchange( aExchange ) + { + } + + +// -------------------------------------------------------------------------- +// Symbian second-phase constructor +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::ConstructL( const TDesC8& aTerminalUri, + const TDesC8& aTerminalId ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::ConstructL" ) + + MUS_LOG_TDESC8( "mus: [MUSAVA] - CMusAvaTerminal::Id ",aTerminalId) + MUS_LOG_TDESC8( "mus: [MUSAVA] - CMusAvaTerminal::MatchL Uri",aTerminalUri ) + iUri = aTerminalUri.AllocL(); + iTerminalId = aTerminalId.AllocL(); + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::ConstructL" ) + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::Id +// -------------------------------------------------------------------------- +// +const TDesC8& CMusAvaTerminal::Id() const + { + return *iTerminalId; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::ToUriL +// -------------------------------------------------------------------------- +// +const TDesC8& CMusAvaTerminal::Uri() const + { + return *iUri; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::MacthL +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::MatchL( const TDesC8& aTerminalUri, + const TDesC8& aTerminalId ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::MatchL" ) + TBool match = EFalse; + TBool useDoubleKeyMatch = Id().Length() > 0 && aTerminalId.Length() > 0; + + MUS_LOG_TDESC8( "mus: [MUSAVA] - CMusAvaTerminal::MatchL aTerminalId ",aTerminalId ) + MUS_LOG_TDESC8( "mus: [MUSAVA] - CMusAvaTerminal::MatchL aTerminalUri ",aTerminalUri ) + if ( useDoubleKeyMatch ) + { + match = Uri().Compare( aTerminalUri ) == 0 && + Id().CompareF( aTerminalId ) == 0; + } + else //not known yet or no terminal id in request i.e. best guess + { + match = Uri().Compare( aTerminalUri ) == 0; + } + + if ( match ) + { + AttachUriL( aTerminalUri ); + AttachIdL( aTerminalId ); + } + + MUS_LOG1( "mus: [MUSAVA] <- CMusAvaTerminal::MatchL = %d",match ) + return match; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::RequestedQuery +// -------------------------------------------------------------------------- +// +const CMusAvaCapability* CMusAvaTerminal::RequestedQuery() const + { + return iRequestedQuery; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::ExecuteQueryL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::ExecuteQueryL( CMusAvaCapabilityQueryBase* aQuery ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::ExecuteQueryL" ) + + __ASSERT_ALWAYS( aQuery , User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( + aQuery->State() == CMusAvaCapabilityQueryBase::ECapabilityQueryCreated, + User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( !iQuery, User::Leave( KErrAlreadyExists ) ); + + ResetAndDestroyQuery(); + + aQuery->ExecuteL(); + + iQuery = aQuery; + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::ExecuteQueryL" ) + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::QueryCompletedL +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::QueryCompletedL( const CSIPClientTransaction& aResponse ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::QueryCompletedL" ) + TBool consumed = EFalse; + + if ( iQuery && iQuery->State() != + CMusAvaCapabilityQueryBase::ECapabilityQueryCompleted ) + { + iQuery->CompletedL( aResponse ); + consumed = iQuery->State() == + CMusAvaCapabilityQueryBase::ECapabilityQueryCompleted; + + if ( consumed ) + { + const CSIPExtensionHeader* userAgent = + MusAvaCapabilityContext::UserAgentHeaderL( aResponse ); + if ( userAgent ) + { + AttachIdL( userAgent->Value() ); + } + } + } + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::QueryCompletedL" ) + + return consumed; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::QueryCanceled +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::QueryCanceled( + const CSIPClientTransaction& aTransaction ) + { + TBool consumed = EFalse; + if ( iQuery && iQuery->State() != + CMusAvaCapabilityQueryBase::ECapabilityQueryCompleted ) + { + iQuery->Canceled( aTransaction ); + consumed = iQuery->State() == + CMusAvaCapabilityQueryBase::ECapabilityQueryCompleted; + } + return consumed; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::QueryExecuting +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::QueryExecuting() + { + TBool executing = EFalse; + if ( iQuery && iQuery->State() == + CMusAvaCapabilityQueryBase::ECapabilityQueryExecuting ) + { + executing = ETrue; + } + return executing; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::QueryRequestedL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::QueryRequestedL( CSIPServerTransaction& aQuery ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::QueryRequestedL" ) + + CSIPResponseElements* response = + CSIPResponseElements::NewLC( + KMUSAVASIP200, + SIPStrings::StringF( SipStrConsts::EPhraseOk ) ); + + CSdpDocument* sdpContent = + CMusAvaCapability::ResponseContentLC( aQuery ); + + RPointerArray headers; + CSIPHeaderBase::PushLC( &headers ); + + if ( PopulateResponseL( aQuery, headers, *sdpContent ) ) + { + RStringF feature = + MusAvaCapabilityContext::SIPStringL( KCapabilitySwisFeature ); + CleanupClosePushL( feature ); + CMusAvaSipheaderUtil::AddAcceptContactHeaderL( headers, + feature ); + CleanupStack::PopAndDestroy(); //feature + MUS_LOG( "mus: [MUSAVA] AddAcceptContactHeaderL -> Success ") + + MUS_LOG( "mus: [MUSAVA] AddAcceptEncodingHeaderL -> Success ") + + MUS_LOG( "mus: [MUSAVA] AddAcceptLanguageHeaderL -> Success ") + CMusAvaSipheaderUtil::AddAcceptSdpHeaderL(headers); + MUS_LOG( "mus: [MUSAVA] AddAcceptSDPHeaderL -> Success ") + AddResponseHeadersL( *response, headers ); + CleanupStack::Pop( &headers ); + AddResponseContentL( *response, *sdpContent ); + } + else + { + CleanupStack::PopAndDestroy( &headers ); + response->SetStatusCodeL( KMUSAVASIPNotImplemented ); + response->SetReasonPhraseL( + SIPStrings::StringF( SipStrConsts::EPhraseNotImplemented ) ); + } + CleanupStack::PopAndDestroy( sdpContent ); + + MUS_LOG( "mus: [MUSAVA] -> Sending Response For Options Request ..." ) + aQuery.SendResponseL( response ); + CleanupStack::Pop( response ); + + iExchange.QueryObserver().CapabilityQueryAnswered( ETrue ); + + // Add sipaddress proposal + if ( response->StatusCode( ) == KMUSAVASIP200 ) + { + + const CSIPContactHeader* contact = + MusAvaCapabilityContext::ContactHeaderL( aQuery ); + + if ( !contact ) + { + MUS_LOG( "mus: [MUSAVA] => FAILED due lack of contact header" ) + } + else + { + /* + const TDesC8& uriInContact = + contact->SIPAddress()->Uri8().Uri().UriDes(); + if ( uriInContact.Length() > 0 ) + { + HBufC* uri = + EscapeUtils::ConvertToUnicodeFromUtf8L( uriInContact ); + CleanupStack::PushL( uri ); + iExchange.QueryObserver().CapabilitiesResolvedL( *uri ); + CleanupStack::PopAndDestroy( uri ); + } + */ + + // If there is P-Asserted-Identity header then send the OPTIONS + // to this. Store it in settings data as To header so then future + // request can be sent there. + + CDesCArrayFlat* pAssertedIdentityHeaders = + MusAvaCapabilityContext::PAssertedIdentityHeaderL( + MusAvaCapabilityContext::MessageElementsL(aQuery)); + CleanupStack::PushL( pAssertedIdentityHeaders ); + __ASSERT_ALWAYS(pAssertedIdentityHeaders,User::Leave(KErrArgument)); + if(pAssertedIdentityHeaders->Count()>0) + { + iExchange.QueryObserver().SipHeadersL(*pAssertedIdentityHeaders, + SipStrConsts::EToHeader); + } + else + { + // P-Asserted-Identity header not exist. So rely on other contacts + // read from phone book or Tel URI to send request. + } + pAssertedIdentityHeaders->Reset(); + CleanupStack::PopAndDestroy( pAssertedIdentityHeaders ); + + TBool sequential = + MultimediaSharingSettings::OperatorVariantSettingL() == + MusSettingsKeys::EOperatorSpecific || + MusSettingsKeys::ESequential == + MultimediaSharingSettings::CapabilityQuerySettingL(); + + TBool alreadyRequested = iExchange.QueryObserver(). + CapabilitiesResolvedForCingular(); + + if ( sequential && !alreadyRequested ) + { + iExchange.QueryObserver().SetCapabilitiesResolvedForCingular(); + } + } + } + + + //if pending query + if ( iQuery ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::QueryRequestedL Executing Pending Query" ) + iQuery->ExecuteL(); + } + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::QueryRequestedL" ) + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::AttachQuery +// -------------------------------------------------------------------------- +// +TInt CMusAvaTerminal::AttachQuery( CMusAvaCapabilityQueryBase& /*aQuery*/ ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::AttachQuery" ) + iQueries++; + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::AttachQuery" ) + return iQueries; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::DetachQuery +// -------------------------------------------------------------------------- +// +TInt CMusAvaTerminal::DetachQuery( CMusAvaCapabilityQueryBase& /*aQuery*/ ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::DetachQuery" ) + iQueries--; + __ASSERT_ALWAYS( iQueries >= 0, + User::Panic( _L("CMusAvaTerminal"), KErrGeneral ) ); + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::DetachQuery" ) + + return iQueries; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::AttachIdL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::AttachIdL( const TDesC8& aTerminalId ) + { + if ( aTerminalId.Length() > 0 ) + { + //terminal id might change + HBufC8* tmpTerminalId = aTerminalId.AllocL(); + delete iTerminalId; + iTerminalId = tmpTerminalId; + } + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::AttachUriL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::AttachUriL( const TDesC8& aUri ) + { + if ( aUri.Length() > 0 ) + { + delete iUri; + iUri = NULL; + iUri = aUri.AllocL(); + } + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::ResetAndDestroyQuery +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::ResetAndDestroyQuery() + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::ResetAndDestroyQuery" ) + CMusAvaCapabilityQueryBase* query = iQuery; + iQuery = NULL; + delete query; + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::ResetAndDestroyQuery" ) + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::PopulateResponseL +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::PopulateResponseL( CSIPServerTransaction& aQuery, + RPointerArray& aResponseHeaders, + CSdpDocument& aSdpContent ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::PopulateResponseL" ) + + TBool supported = EFalse; + + const CSIPAcceptContactHeader* featureSet = + MusAvaCapabilityContext::AcceptContactHeaderL( aQuery ); + + User::LeaveIfError( !featureSet ? KErrGeneral : KErrNone ); + + for( TInt i = 0; i < iExchange.Capabilities().Count();i++ ) + { + CMusAvaCapability* capability = iExchange.Capabilities()[ i ]; + TBool containsFeature = capability->Supports( *featureSet ); + supported = containsFeature ? ETrue : supported; + + if ( containsFeature ) + { + const CSIPMessageElements& elements = + MusAvaCapabilityContext::MessageElementsL( aQuery ); + const TDesC8& content = elements.Content(); + CSdpDocument* sdp = NULL; + + if ( content.Length() > 0 ) + { + sdp = CSdpDocument::DecodeLC( content ); + } + else + { + sdp = CSdpDocument::NewLC(); + } + + //store video codecs that came from the other terminal + CDesCArrayFlat* videoCodecs = CMusAvaCapability::ResolveCodecsL( *sdp ); + CleanupStack::PushL( videoCodecs ); + capability->Exchange().QueryObserver().VideoCodecsResolvedL( *videoCodecs ); + CleanupStack::PopAndDestroy( videoCodecs ); + + //store fast startup mode if present + MusSettingsKeys::TFastMode mode = + CMusAvaCapability::ResolveFastModeL( *sdp ); + capability->Exchange().QueryObserver().FastModeResolved( mode ); + + CleanupStack::PopAndDestroy( sdp ); + + capability->PopulateResponseL( aQuery, + aResponseHeaders, + aSdpContent ); + iRequestedQuery = capability; + } + } + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::PopulateResponseL" ) + + return supported; + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::AddResponseHeadersL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::AddResponseHeadersL( CSIPResponseElements& aResponse, + RPointerArray& aResponseHeaders ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::AddResponseHeadersL" ) + + CSIPMessageElements& message = aResponse.MessageElements(); + + if ( iExchange.TerminalId().Length() > 0 ) + { + //terminal id + CSIPHeaderBase* userAgent = + MusAvaCapabilityContext::UserAgentHeaderLC( + iExchange.TerminalId() ); + aResponseHeaders.AppendL( userAgent ); + CleanupStack::Pop( userAgent ); + } + + //Set user headers + message.SetUserHeadersL( aResponseHeaders ); + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::AddResponseHeadersL" ) + } + + +// -------------------------------------------------------------------------- +// CMusAvaTerminal::AddResponseContentL +// -------------------------------------------------------------------------- +// +void CMusAvaTerminal::AddResponseContentL( CSIPResponseElements& aResponse, + CSdpDocument& aSdpContent ) + { + MUS_LOG( "mus: [MUSAVA] -> CMusAvaTerminal::AddResponseContentL" ) + + CSIPMessageElements& message = aResponse.MessageElements(); + + //create content from SDP document + HBufC8* content = MusAvaCapabilityContext::ToTextL( aSdpContent ); + CleanupStack::PushL( content ); + + //create content type + CSIPContentTypeHeader* contentTypeHeader = NULL; + contentTypeHeader = + CSIPContentTypeHeader::NewLC( KMUSAVASIPMediaTypeApplication, + KMUSAVASIPMediaSubTypeSDP ); + + //set content + message.SetContentL( content, contentTypeHeader ); + CleanupStack::Pop( contentTypeHeader ); + CleanupStack::Pop( content ); + + MUS_LOG( "mus: [MUSAVA] <- CMusAvaTerminal::AddResponseContentL" ) + } +// -------------------------------------------------------------------------- +// CMusAvaTerminal::IsDiscovered +// -------------------------------------------------------------------------- +// +TBool CMusAvaTerminal::IsDiscovered() + { + TBool isDiscovered = EFalse; + TBool isGarbage = !iQueries && !RequestedQuery(); + + if ( !isGarbage ) + { + isDiscovered = + iQueries == 1 && + iQuery && + iQuery->State() == CMusAvaCapabilityQueryBase::ECapabilityQueryCompleted; + } + else + { + isDiscovered = ETrue; + } + + return isDiscovered; + + }