/*
* 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: Sent capability query (OPTIONS)
*
*/
#include "musavacapabilityquerybase.h"
#include "muscleanupresetanddestroy.h"
#include <escapeutils.h>
#include <sipconnection.h>
#include <sipprofile.h>
#include <sipclienttransaction.h>
#include <sipmessageelements.h>
#include <siprequestelements.h>
#include <sipextensionheader.h>
#include <sipacceptcontactheader.h>
#include <sipcontactheader.h>
#include <sipacceptheader.h>
#include <sipstrings.h>
#include <sipstrconsts.h>
#include <sipresponseelements.h>
#include <sipaddress.h>
#include <sdpdocument.h>
#include <sdporiginfield.h>
#include <sdpconnectionfield.h>
#include <sdpattributefield.h>
#include <sdpmediafield.h>
#include <e32math.h>
#include "mussettings.h"
#include "muslogger.h"
#include "mmusavacapabilityqueryobserver.h"
#include "musavacapability.h"
#include "musavacapabilityexchange.h"
#include "musavaterminal.h"
#include "musavacapabilitycontext.h"
#include "musavasipheaderutil.h"
// --------------------------------------------------------------------------
// C++ constructor
// --------------------------------------------------------------------------
//
CMusAvaCapabilityQueryBase::CMusAvaCapabilityQueryBase(
CMusAvaCapability& aCapability,
CSIPConnection& aSIPConnection,
CSIPProfile& aProfile )
: iCapability( aCapability ),
iSIPConnection( aSIPConnection ),
iProfile( aProfile ),
iState( ECapabilityQueryCreated ),
iResult( KCapabilityQueryNotReady )
{
}
// --------------------------------------------------------------------------
// C++ destructor
// --------------------------------------------------------------------------
//
CMusAvaCapabilityQueryBase::~CMusAvaCapabilityQueryBase()
{
MUS_LOG(
"mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::~CMusAvaCapabilityQueryBase" )
delete iRegisteredContact;
delete iOriginator;
if ( iTerminal )
{
iTerminal->DetachQuery( *this );
}
ResetAndDestroyTrx();
MUS_LOG( "mus: [MUSAVA] -> StringPools are getting closed." )
MUS_LOG(
"mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::~CMusAvaCapabilityQueryBase" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::ConstructL
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::ConstructL( const TDesC& aSipAddress )
{
MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::ConstructL" )
// If string pool is opened already , then dont care.
User::LeaveIfError( aSipAddress.Length() > 0 ? KErrNone : KErrArgument );
// If it is not registered , just leave.
TBool isRegistered = ETrue;
iProfile.GetParameter( KSIPProfileRegistered, isRegistered );
User::LeaveIfError( isRegistered ? KErrNone : KErrArgument );
TInt err( KErrNotFound );
const TDesC8* registeredContact( NULL );
err = iProfile.GetParameter( KSIPRegisteredContact, registeredContact );
if( err )
{
MUS_LOG1( "mus: [MUSAVA] iProfile.GetParameter Contact -> %d", err )
User::LeaveIfError( err );
}
// contactHeader array will only contain one instance of CSIPContactHeader,
// since only one registered contact is decoded
RPointerArray<CSIPContactHeader> contactHeader =
CSIPContactHeader::DecodeL( *registeredContact );
MusCleanupResetAndDestroyPushL( contactHeader );
// leave if there is at least one contact not present
if ( contactHeader.Count() < 1 )
{
MUS_LOG1( "mus: [MUSAVA] contactHeader has %d instances, instead of 1",
contactHeader.Count() );
User::Leave( KErrNotFound );
}
// if more contact than pick the first one. Sip assures in idle case
// it should always return only one registered contact.
CSIPAddress* sipAddress = contactHeader[0]->SIPAddress();
if ( !sipAddress )
{
MUS_LOG( "mus: [MUSAVA] name-address not present")
User::Leave( KErrNotFound );
}
iRegisteredContact = CUri8::NewL( sipAddress->Uri8().Uri() );
MUS_LOG_TDESC8( " mus: [MUSAVA] iRegisteredContact : ", (iRegisteredContact->Uri().UriDes()));
CleanupStack::PopAndDestroy( &contactHeader );
sipAddress = NULL;
const MDesC8Array* aors = NULL;
User::LeaveIfError(iProfile.GetParameter( KSIPRegisteredAors, aors ));
MUS_LOG( "mus: [MUSAVA] iProfile.GetParameter -> OK " )
if( !aors || aors->MdcaCount() <= 0 ) User::Leave(KErrArgument);
MUS_LOG_TDESC8( " mus: [MUSAVA] AOR -> 0 : ", aors->MdcaPoint(0));
sipAddress = CSIPAddress::DecodeL( aors->MdcaPoint(0) );
MUS_LOG( "mus: [MUSAVA] CSIPAddress::DecodeL -> OK " )
CleanupStack::PushL( sipAddress );
iOriginator = CUri8::NewL(sipAddress->Uri8().Uri());
MUS_LOG_TDESC8( " mus: [MUSAVA] iOriginator : ", (iOriginator->Uri().UriDes()));
CleanupStack::PopAndDestroy(sipAddress);
HBufC8* sipAddress8 = EscapeUtils::ConvertFromUnicodeToUtf8L( aSipAddress );
CleanupStack::PushL( sipAddress8 );
iTerminal = &Capability().Exchange().TerminalL( sipAddress8->Des() );
CleanupStack::PopAndDestroy( sipAddress8 ) ;
iTerminal->AttachQuery( *this );
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::ConstructL" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::Capability
// --------------------------------------------------------------------------
//
const CMusAvaCapability& CMusAvaCapabilityQueryBase::Capability() const
{
return iCapability;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::SetState
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::SetState(
CMusAvaCapabilityQueryBase::TState aState )
{
iState = aState;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::SetResult
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::SetResult( TInt aResult )
{
iResult = aResult;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::Terminal
// --------------------------------------------------------------------------
//
CMusAvaTerminal& CMusAvaCapabilityQueryBase::Terminal()
{
return *iTerminal;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::ExecuteL
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::ExecuteL()
{
MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::ExecuteL" )
__ASSERT_ALWAYS(
State() != ECapabilityQueryPrepared, User::Leave( KErrGeneral ) );
if ( State() == ECapabilityQueryCreated )
{
RPointerArray<CSIPHeaderBase> headers;
CSIPHeaderBase::PushLC( &headers );
Prepare( headers );
if ( State() == ECapabilityQueryPrepared )
{
CMusAvaSipheaderUtil::AddAcceptContactHeaderL( headers,
Capability().Feature() );
MUS_LOG( "mus: [MUSAVA] AddAcceptContactHeaderL -> Success ")
CMusAvaSipheaderUtil::AddAcceptEncodingHeaderL(headers);
MUS_LOG( "mus: [MUSAVA] AddAcceptEncodingHeaderL -> Success ")
CMusAvaSipheaderUtil::AddAcceptLanguageHeaderL(headers);
MUS_LOG( "mus: [MUSAVA] AddAcceptLanguageHeaderL -> Success ")
CMusAvaSipheaderUtil::AddAcceptSdpHeaderL(headers);
MUS_LOG( "mus: [MUSAVA] AddAcceptSDPHeaderL -> Success ")
CMusAvaSipheaderUtil::AddPreferredIdentityHeaderL(headers,
iOriginator->Uri().UriDes());
MUS_LOG( "mus: [MUSAVA] AddPreferredIdentityHeaderL -> Success ")
AddContactHeaderL( headers );
MUS_LOG( "mus: [MUSAVA] AddContactHeaderL -> Success ")
//terminal ID
if ( Capability().Exchange().TerminalId().Length() > 0 )
{
MUS_LOG( "mus: [MUSAVA] Adding User-Agent header" )
CSIPHeaderBase* userAgent =
MusAvaCapabilityContext::UserAgentHeaderLC(
Capability().Exchange().TerminalId() );
headers.AppendL( userAgent );
CleanupStack::Pop( userAgent );
}
//remote uri ( will be used as ToHeader )
CUri8* remoteUri =
MusAvaCapabilityContext::ToUriL( Terminal().Uri() );
CleanupStack::PushL( remoteUri );
CSIPRequestElements* request =
CSIPRequestElements::NewL( remoteUri );
CleanupStack::Pop( remoteUri );
CleanupStack::PushL( request );
request->SetMethodL(
SIPStrings::StringF( SipStrConsts::EOptions ) );
CSIPMessageElements& message = request->MessageElements();
message.SetUserHeadersL( headers );
HBufC8* content = ContentLC();
CMusAvaSipheaderUtil::AddSdpL(request,content);
CleanupStack::Pop(content) ;
ResetAndDestroyTrx();
MUS_LOG( "mus: [MUSAVA] Sending OPTIONS request ...." )
iTrx = iSIPConnection.SendRequestL( request, iProfile );
CleanupStack::Pop( request );
iState = ECapabilityQueryExecuting;
MUS_LOG( "mus: [MUSAVA] OPTIONS request sent" )
}
CleanupStack::PopAndDestroy( &headers );
}
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::ExecuteL" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::CompletedL
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::CompletedL(
const CSIPClientTransaction& aResponse )
{
MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::CompletedL" )
if ( iTrx && *iTrx == aResponse )
{
TUint statusCode = aResponse.ResponseElements()->StatusCode();
if ( 100 <= statusCode && statusCode < 200 )
{
return;
}
DoCompletedL( aResponse );
if ( State() == ECapabilityQueryCompleted )
{
MUS_LOG( "mus: [MUSAVA] query completed" )
Capability().Exchange().QueryObserver().CapabilitiesResolved(
*this );
}
}
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::CompletedL" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::Canceled
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::Canceled(
const CSIPClientTransaction& aTransaction )
{
MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::Canceled" )
if ( iTrx && *iTrx == aTransaction )
{
MUS_LOG( "mus: [MUSAVA] query canceled" )
SetState( ECapabilityQueryCompleted );
SetResult( KCapabilityCapabilitesNotFound );
Capability().Exchange().QueryObserver().CapabilitiesResolved(
*this );
}
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::Canceled" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::AddContactHeaderL
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::AddContactHeaderL(
RPointerArray<CSIPHeaderBase>& aRequestHeaders )
{
MUS_LOG(
"mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::AddContactHeaderL" )
CSIPContactHeader* contact =
MusAvaCapabilityContext::ContactHeaderLC( *iRegisteredContact,
Capability().Feature() );
aRequestHeaders.AppendL( contact );
CleanupStack::Pop( contact );
MUS_LOG(
"mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::AddContactHeaderL" )
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::State
// --------------------------------------------------------------------------
//
CMusAvaCapabilityQueryBase::TState CMusAvaCapabilityQueryBase::State() const
{
return iState;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::Result
// --------------------------------------------------------------------------
//
TInt CMusAvaCapabilityQueryBase::Result() const
{
return iResult;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::ResetAndDestroyTrx
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::ResetAndDestroyTrx()
{
delete iTrx;
iTrx = NULL;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::LocalAddress
// --------------------------------------------------------------------------
//
const CUri8& CMusAvaCapabilityQueryBase::LocalAddress() const
{
return *iOriginator;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::ResponseContentLC
// --------------------------------------------------------------------------
//
HBufC8* CMusAvaCapabilityQueryBase::ContentLC()
{
MUS_LOG("mus: [MUSAVA]: -> CMusAvaCapabilityQueryBase::ContentLC" )
CSdpDocument* content = CSdpDocument::NewLC();
RStringPool strPool = SdpCodecStringPool::StringPoolL();
RStringF netType =
MusAvaCapabilityContext::SDPStringL( SdpCodecStringConstants::ENetType );
_LIT8(KOriginFieldUser1, "-");
_LIT8(KSessionName, "-");
content->SetSessionNameL( KSessionName );
TPtrC8 localHost;
RStringF hostType;
TTime now;
now.UniversalTime();
TInt64 rand = now.Int64();
TInt64 sessionID = Math::Rand( rand );
hostType = strPool.StringF( SdpCodecStringConstants::EAddressTypeIP4,
SdpCodecStringPool::StringTableL() );
MUS_LOG( "EAddressTypeIP4 from string pool" )
TInetAddr aAddr(0);
iSIPConnection.GetLocalAddrL(aAddr);
TBuf<50> ipAddress;
aAddr.Output(ipAddress);
MUS_LOG_TDESC( "mus: [MUSAVA]: LocalIP Address",ipAddress )
HBufC8 * ipaddr8=HBufC8::NewLC(ipAddress.Length());
ipaddr8->Des().Copy(ipAddress);
MUS_LOG( "mus: [MUSAVA]: SetOriginField" )
CSdpOriginField* originField = CSdpOriginField::NewL( KOriginFieldUser1,
sessionID,
sessionID,
netType,
hostType,
*ipaddr8);
content->SetOriginField( originField );
// Connection field
MUS_LOG( "mus: [MUSAVA]: SetConnectionField" )
CSdpConnectionField* connectionField =
CSdpConnectionField::NewL( netType, hostType,*ipaddr8);
content->SetConnectionField( connectionField );
CleanupStack::PopAndDestroy(ipaddr8);
OtherSDPHeadersL(*content);
MUS_LOG( "mus: [MUSAVA]: Constructing the Sdp Content" )
CBufFlat* encBuf = CBufFlat::NewL( KMUSAVAMaxLengthOfSDPMessage );
CleanupStack::PushL( encBuf );
RBufWriteStream writeStream( *encBuf, 0 );
writeStream.PushL();
content->EncodeL( writeStream );
CleanupStack::PopAndDestroy();//writeStream
HBufC8* textContent = encBuf->Ptr( 0 ).AllocL();
CleanupStack::PopAndDestroy( encBuf );
CleanupStack::PopAndDestroy(content);
CleanupStack::PushL(textContent);
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::ContentLC" )
return textContent;
}
// --------------------------------------------------------------------------
// CMusAvaCapabilityQueryBase::OtherSDPHeadersL
// --------------------------------------------------------------------------
//
void CMusAvaCapabilityQueryBase::OtherSDPHeadersL( CSdpDocument& aResponseContent )
{
MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQueryBase::OtherSDPHeadersL" )
MUS_LOG( "mus: [MUSAVA] Adding application attribute to SDP" )
//application
CSdpAttributeField* application = CSdpAttributeField::NewLC(
MusAvaCapabilityContext::SDPStringL(
SdpCodecStringConstants::EMediaApplication ),
KCapabilitySwisApplication );
aResponseContent.AttributeFields().AppendL( application );
CleanupStack::Pop( application );
MUS_LOG( "mus: [MUSAVA] Adding type attribute to SDP" )
//type
RStringF typeStr = MusAvaCapabilityContext::SDPStringL(
KCapabilitySDPAttributeNameType );
CleanupClosePushL( typeStr );
CSdpAttributeField* type =
CSdpAttributeField::NewL( typeStr, KCapabilitySDPAttributeType );
CleanupStack::PopAndDestroy();//typeStr
CleanupStack::PushL( type );
aResponseContent.AttributeFields().AppendL( type );
CleanupStack::Pop( type );
// Fast startup mode
CMusAvaCapability::AddFastModeL( aResponseContent );
MUS_LOG( "mus: [MUSAVA] Adding media line to SDP" )
//media line
CSdpMediaField* mediaLine = CSdpMediaField::NewLC(
MusAvaCapabilityContext::SDPStringL
(SdpCodecStringConstants::EMediaVideo ),
NULL,
MusAvaCapabilityContext::SDPStringL
(SdpCodecStringConstants::EProtocolRtpAvp ),
KCapabilitySwisFormatListH263Only );
//adding H.264 codec to SDP
if( !MultimediaSharingSettings::IsAvcDisabled())
{
MUS_LOG( "mus: [MUSAVA] - Adding avc to supported codec list" )
// reconstruct media line with H264 and H263
CleanupStack::PopAndDestroy(mediaLine);
mediaLine = CSdpMediaField::NewLC(
MusAvaCapabilityContext::SDPStringL
(SdpCodecStringConstants::EMediaVideo ),
NULL,
MusAvaCapabilityContext::SDPStringL
(SdpCodecStringConstants::EProtocolRtpAvp ),
KCapabilitySwisFormatList );
CSdpFmtAttributeField* rtpMapH264 =
CMusAvaCapability::RtpMapLineLC( KCapabilitySDPAttributeCodecH264,
KCapabilitySDPAttributePayloadTypeH264,
KCapabilitySDPAttributeClockrate );
mediaLine->FormatAttributeFields().AppendL( rtpMapH264 );
CleanupStack::Pop( rtpMapH264 );
}
//H.263 codec
MUS_LOG( "mus: [ENGINE] - Adding h263 to supported codec list" )
CSdpFmtAttributeField* rtpMapH263 =
CMusAvaCapability::RtpMapLineLC( KCapabilitySDPAttributeCodecH263,
KCapabilitySDPAttributePayloadType,
KCapabilitySDPAttributeClockrate );
mediaLine->FormatAttributeFields().AppendL( rtpMapH263 );
CleanupStack::Pop( rtpMapH263 );
aResponseContent.MediaFields().AppendL( mediaLine );
CleanupStack::Pop( mediaLine );
MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQueryBase::OtherSDPHeadersL" )
}