// Copyright (c) 2005-2009 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:
// Name        : sipietfprofilecontext.cpp
// Part of     : sip ietf agent
// implementation
// Version     : 1.0
//




// INCLUDE FILES
#include "sipietfprofilecontext.h"
#include "sipprflstatebase.h"
#include "sipconcreteprofile.h"
#include "sipietfprofileagent.h"
#include "sipregistrationbinding.h"
#include "sipclienttransaction.h"
#include "siprouteheader.h"
#include "sipgendefs.h"
#include "siprefresh.h"
#include "sipmessagebuilder.h"
#include "sipaddress.h"
#include "siptoheader.h"
#include "siprouteheader.h"
#include "sipmessageelements.h"
#include "sipresponseelements.h"
#include "sipsecurityclientheader.h"
#include "sipconnection.h"
#include "SipProfileLog.h"
#include "sipstrings.h"
#include "sipstrconsts.h"
#include "siperr.h"
#include "sipcodecerr.h"
#include "sipcontactheader.h"
#include <sipprofile.h>
#include <bamdesca.h>
#include <e32math.h>
#include <uri8.h>
#include <uriutils.h>

_LIT8(KNATTraversalRequiredDes, "nat_traversal_required");
_LIT8(KSIPTls, "tls");
_LIT8(KTransportUdpParam, "transport=udp");
_LIT8(KTransportTcpParam, "transport=tcp");
_LIT8(KTransportTlsParam, "transport=tls");

const TUint KMaxRandomLimit = 50;
const TUint KBaseTimeInSec	= 30;
const TUint KWaitTimeCoefficient = 2;
const TUint KRandomDivider		= 100;
const TUint KMaxRetryForOneAddress = 9;

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::NewLC
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSIPIetfProfileContext* CSIPIetfProfileContext::NewLC(
	CSIP& aSIP,
	CSIPIetfConnectionContext& aConnection, 
	MSIPProfileAgentObserver& aObserver,
	CSIPPrflStateBase& aInitState,
	CSIPConcreteProfile& aProfile,
	CDeltaTimer& aDeltaTimer,
	CSipProfileAgentConfigExtension& aConfigExtension)
	{
	CSIPIetfProfileContext* self = new (ELeave) CSIPIetfProfileContext(aSIP,
		aConnection, aObserver, aInitState, aProfile, aDeltaTimer,aConfigExtension);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::NewL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSIPIetfProfileContext* CSIPIetfProfileContext::NewL(
	CSIP& aSIP,
	CSIPIetfConnectionContext& aConnection, 
	MSIPProfileAgentObserver& aObserver,
	CSIPPrflStateBase& aInitState,
	CSIPConcreteProfile& aProfile,
	CDeltaTimer& aDeltaTimer,
	CSipProfileAgentConfigExtension& aConfigExtension)
	{
	CSIPIetfProfileContext* self = CSIPIetfProfileContext::NewLC(
		aSIP, aConnection, aObserver, aInitState, aProfile, aDeltaTimer,aConfigExtension);
	CleanupStack::Pop();
	return self;
	}
	
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CSIPIetfProfileContext
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSIPIetfProfileContext::CSIPIetfProfileContext(
	CSIP& aSIP,
	CSIPIetfConnectionContext& aConnection,
	MSIPProfileAgentObserver& aObserver,
	CSIPPrflStateBase& aInitState,
	CSIPConcreteProfile& aProfile,
	CDeltaTimer& aDeltaTimer,
	CSipProfileAgentConfigExtension& aConfigExtension)
	: CSIPProfileContextBase(aSIP,
	                         *(aConnection.Connection()),
	                         aObserver,
	                         aInitState,
	                         aProfile,
	                         aDeltaTimer),
	  iConnectionContext(aConnection),
	  iRetryTimerUse(EFalse),
	  iConfigExtension(aConfigExtension)
	{
	iRandomSeed = 0;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::ConstructL
// -----------------------------------------------------------------------------
//	
void CSIPIetfProfileContext::ConstructL()
    {
    iStrNATTraversalRequired = 
        SIPStrings::Pool().OpenFStringL(KNATTraversalRequiredDes);
    }

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::~CSIPIetfProfileContext
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSIPIetfProfileContext::~CSIPIetfProfileContext()
	{
	iStrNATTraversalRequired.Close();
	}
	
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::DestroyRegistration()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::DestroyRegistration()
	{
	PROFILE_DEBUG3("SIPIetfProfileContext::DestroyRegistration", ProfileId())
	delete iRegistration;
	iRegistration = 0;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CreateRegistrationL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::CreateRegistrationL()
	{
	ASSERT(iProfile);
    RStringF transport(SIPStrings::StringF(SipStrConsts::EEmpty));
    CleanupClosePushL(transport);
	CSIPRouteHeader* proxy = 0;
	CUri8* remoteUri = 0;
	CSIPRefresh* refresh = CSIPRefresh::NewLC();
	CSIPToHeader* to = SIPMessageBuilder::CreateToLC(iProfile->AOR());
	to->SetParamL(iStrNATTraversalRequired);
	TUint pops = 2; //initial amount to pop from CleanupStack
    
	const TDesC8& proxyAddr = ProxyAddressL();
	HBufC8* sipsproxy = NULL;
	if(IsAddressSIPSURIL(iProfile->AOR()) && proxyAddr.Length() > 0)
		{
		if (!IsProxyResolvingEnabled())
			{
			__ASSERT_ALWAYS (IsAddressSIPSURIL(proxyAddr), 
						User::Leave(KErrArgument));
			}
		else
			{
			sipsproxy = SetAddressToSIPSURIL(proxyAddr);
			CleanupStack::PushL(sipsproxy);
			pops++;
			}
		__ASSERT_ALWAYS (!iProfile->IsSecurityNegotiationEnabled(), 
					User::Leave(KErrArgument));	
		}
		
	if (!sipsproxy)
		{
		sipsproxy = proxyAddr.AllocLC();
		pops++;
		}

	if (sipsproxy->Length()) //there's an outbound proxy defined
		{
		(iProfile->IsSigCompEnabled())?
		proxy = SIPMessageBuilder::CreateRouteLC(*sipsproxy, ETrue):
		proxy = SIPMessageBuilder::CreateRouteLC(*sipsproxy);
		pops++;
		RStringF proxyTransport = TransportProtocol(proxy->SIPAddress().Uri8());	
		if (proxyTransport.DesC().Length() > 0)
			{
			transport = proxyTransport.Copy();
			}		
		}
		
	if (iProfile->Server(KSIPRegistrar).Length()) //there's a registrar defined
		{
        TUriParser8 parser;
        User::LeaveIfError(parser.Parse(iProfile->Server(KSIPRegistrar)));
        remoteUri = CUri8::NewLC(parser);			
	    pops++;
		if (!proxy)
			{
			RStringF registrarTransport = TransportProtocol(*remoteUri);		
		    if (registrarTransport.DesC().Length() > 0)
			    {
			    transport = registrarTransport.Copy();
			    }
			}
        }		

	TBool sigcomp = iProfile->IsSigCompEnabled();
	
	const TDesC8* user = NULL;
	User::LeaveIfError(
		iProfile->ExtensionParameter(KSIPContactHeaderUser,user));
	
	CSIPContactHeader* contact =
	    SIPMessageBuilder::CreateContactLC(*user, 
	    		iConfigExtension.ExpiryValueL(TSIPProfileTypeInfo::EInternet,
				CSipProfileAgentConfigExtension::EProfileRegistrationValue),
	    		iProfile->ContactHeaderParams(),
	    		transport, sigcomp);
    pops++;

	if (IsAddressSIPSURIL(iProfile->AOR()))
		{
		CUri8* contactUriClone = 
		    CUri8::NewLC(contact->SIPAddress()->Uri8().Uri());
        contactUriClone->SetComponentL(
            SIPStrings::StringF(SipStrConsts::ESips).DesC(),EUriScheme);
        contactUriClone->SetComponentL(*user,EUriUserinfo);            	
		contact->SIPAddress()->SetUri8L(contactUriClone);
		CleanupStack::Pop(contactUriClone);
		}
	
	iRegistration = CSIPRegistrationBinding::NewL(iConnection, to, contact,
	                                              refresh, proxy, remoteUri);
	CleanupStack::Pop(pops);
	delete sipsproxy;
	CleanupStack::PopAndDestroy(1); // transport
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CreateMsgElementsLC()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSIPMessageElements* CSIPIetfProfileContext::CreateMsgElementsLC()
	{
	ASSERT(iProfile);
	
	CSIPMessageElements* elements = CSIPMessageElements::NewLC();
	
	RPointerArray<CSIPHeaderBase> headers;
	CSIPHeaderBase::PushLC(&headers);
	if (SetTlsToSecurityClientL())
		{
		CSIPSecurityClientHeader* sclient = 
		    CSIPSecurityClientHeader::NewLC(KSIPTls);
		headers.AppendL(sclient);
		CleanupStack::Pop(sclient);
		}
		
	if (iProfile->IsSecurityNegotiationEnabled())
		{
		CSIPSecurityClientHeader* sclient = 
		    CSIPSecurityClientHeader::NewLC(KSIPdigest);
		headers.AppendL(sclient);
		CleanupStack::Pop(sclient);
		}
		
	TInt sipHeaderCount = iProfile->SIPHeaders().MdcaCount();
	for (TInt i=0; i < sipHeaderCount; i++)
	    {
	    TPtrC8 headerDes(iProfile->SIPHeaders().MdcaPoint(i));
	    CSIPHeaderBase* header = SIPMessageBuilder::CreateHeaderLC(headerDes);
	    headers.AppendL(header);
	    CleanupStack::Pop(header);
	    }   
	
	elements->SetUserHeadersL(headers); // // An empty array is also allowed
	CleanupStack::Pop(1); // headers
	    
	return elements;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CreateDeRegisterElementsL()
// -----------------------------------------------------------------------------
//	
CSIPMessageElements* CSIPIetfProfileContext::CreateDeRegisterElementsL()
    {
    return NULL;
    }

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::UpdateContactHeaderParamsL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::UpdateContactHeaderParamsL(
    CSIPConcreteProfile& aNewProfile)
	{
	CSIPContactHeader& contact = Registration()->ContactHeader();
    TPtrC8 paramName;
	TPtrC8 paramValue;

	for (TInt i = Profile()->ContactHeaderParams().MdcaCount()-1;i >= 0; i--)
		{
		TPtrC8 param(Profile()->ContactHeaderParams().MdcaPoint(i));
		SIPMessageBuilder::ParseParamL(param,paramName,paramValue);		
		RStringF name = SIPStrings::Pool().OpenFStringL(paramName);
		CleanupClosePushL(name);
		contact.DeleteParam(name);
		CleanupStack::PopAndDestroy(1); // name
		}

	for (TInt i = 0; &(aNewProfile.ContactHeaderParams()) && 
				     (i < aNewProfile.ContactHeaderParams().MdcaCount()); i++)
		{
		TPtrC8 param(aNewProfile.ContactHeaderParams().MdcaPoint(i));
		TBool hasValue = 
		    SIPMessageBuilder::ParseParamL(param,paramName,paramValue);
		RStringF name = SIPStrings::Pool().OpenFStringL(paramName);
		CleanupClosePushL(name);
		if (hasValue)
			{
			RStringF value = SIPStrings::Pool().OpenFStringL(paramValue);
			CleanupClosePushL(value);
			contact.SetParamL(name,value);
			CleanupStack::PopAndDestroy(1); // value
			}
		else
			{
			contact.SetParamL(name);	
			}
		CleanupStack::PopAndDestroy(1); // name	
		}
	
	CSIPMessageElements* elements = CreateMsgElementsForUpdateLC(aNewProfile);
	SetTransaction(Registration()->UpdateL(
			iConfigExtension.ExpiryValueL(TSIPProfileTypeInfo::EInternet,
			CSipProfileAgentConfigExtension::EProfileRegistrationValue),
			elements));
	CleanupStack::Pop(elements);
	}
	
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::SetRegisteredAORsL()
// -----------------------------------------------------------------------------
//	
void CSIPIetfProfileContext::SetRegisteredAORsL()
    {
    if (iProfile)
        {
        CDesC8ArrayFlat* array = new(ELeave)CDesC8ArrayFlat(1);
	    CleanupStack::PushL(array);    
        array->AppendL(iProfile->AOR());
	    iProfile->SetRegisteredAORsL(*array);
	    CleanupStack::PopAndDestroy(array);
	    if (iRegistration && iRegistration->RegisteredContact())
	        {
	        HBufC8* contact = 
	            iRegistration->RegisteredContact()->ToTextValueLC();
	        iProfile->SetExtensionParameterL(KSIPRegisteredContact,*contact);
	        CleanupStack::PopAndDestroy(contact);
	        }
        }
    }

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::ResolveProxyL
// -----------------------------------------------------------------------------
//	
void CSIPIetfProfileContext::ResolveProxyL()
    {
    iConnectionContext.ResolveL();
    }
       
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CancelProxyResolving
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::CancelProxyResolving()
    {
    iConnectionContext.CleanProxyResolving();
    }	

// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::RetryAfterTimer
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//	
TBool CSIPIetfProfileContext::RetryAfterTimer()
	{
	return ( iRetryCounterSum == 0 && iRetryTimerUse );
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::RetryRegister
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//	
TBool CSIPIetfProfileContext::RetryRegister( 
    CSIPClientTransaction* /*aTransaction*/,
    TInt aError )
	{
	PROFILE_DEBUG4("CSIPIetfProfileContext::RetryRegister",
	               aError, iRetryCounterSum)

	TBool retry = EFalse;
		
	if (iProfile &&
	    AgentObserver().ProceedRegistration(*iProfile, aError) &&
	    (CurrentState() == MSIPProfileContext::ERegistrationInProgress ||
	     CurrentState() == MSIPProfileContext::ERegistered) &&
		(aError == KErrSIPOutboundProxyNotResponding || 
		 aError == KErrSIPResolvingFailure || 
		 aError == KErrTimedOut || 
		 aError == KErrSIPTransportFailure ||
		 aError == KErrSIPICMPFailure  && 
		 iConnection.State() != CSIPConnection::ESuspended))		
	    {
		if ( iRetryCounterSum + 1 < KMaxRetryForOneAddress &&
		     iRetryCounter < KMaxRetryForOneAddress )
			{
			retry = ETrue;
			}
		else
			{
			if (iRetryCounterSum < KMaxRetryForOneAddress && 
			    iRetryCounter + 1 >= KMaxRetryForOneAddress ||
			    iRetryCounter >=  KMaxRetryForOneAddress)
				{
				iRetryCounter = 0;
				retry = RetryPossible(aError);
				}
			else
				{
				retry = ETrue;
				}
			}
		iRetryTimerUse = retry;
		SetRetryPossible(retry);
		}
	else
		{
		iRetryCounter = 0;
		iRetryCounterSum = 0;
		iRetryTimerUse = EFalse;
		}
	if (!retry)
		{
		iRetryCounter = 0;
		iRetryCounterSum = 0;
		}
	return retry;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::ShouldRetryRegistration
// -----------------------------------------------------------------------------
//	
TBool CSIPIetfProfileContext::ShouldRetryRegistration( TInt aError )
	{
	return (aError == K503ServiceUnavailable || 
		    aError == KErrSIPOutboundProxyNotResponding || 
		    aError == KErrTimedOut ||
		    ((aError == KErrSIPResolvingFailure || 
		      aError == KErrSIPTransportFailure ||
		      aError == KErrSIPICMPFailure) && 
			 iConnection.State() != CSIPConnection::ESuspended));
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::InitializeRetryTimerValue
// -----------------------------------------------------------------------------
//	
void CSIPIetfProfileContext::InitializeRetryTimerValue()
	{
	iRetryTimerUse = 0;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::ConnectionStateChangedImpl
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::ConnectionStateChangedImpl(
    CSIPConnection::TState /*aState*/)
    {
    }

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::DeregisterL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::DeregisterL()
	{
	PROFILE_DEBUG4("CSIPIetfProfileContext::DeregisterL", ProfileId()\
		, iCurrentState->Name())
	iCurrentState->DeregisterL(*this);
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::UpdateL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::UpdateL(
	CSIPConcreteProfile& aNewProfile)
	{
	PROFILE_DEBUG4("CSIPIetfProfileContext::UpdateL", ProfileId()\
		, iCurrentState->Name())
	iCurrentState->UpdateL(*this, aNewProfile);
	}
	
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::IncomingResponse()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CSIPIetfProfileContext::IncomingResponse(
	CSIPClientTransaction& aTransaction,
	CSIPRegistrationBinding& aRegistration,
	TBool& aHandled)
	{
	if (iClientTx && iRegistration && 
		aTransaction==*iClientTx && aRegistration==*iRegistration)
		{
		PROFILE_DEBUG3("SIPIetfProfileContext::IncomingResponse", ProfileId())
		aHandled = ETrue;
		const CSIPResponseElements* response = aTransaction.ResponseElements();
		if (response)
		    {
		    TUint responseCode = response->StatusCode();
		    if (responseCode >= K300MultipleChoices)
		        {
		        PROFILE_DEBUG1("IETFProfileContext: registration failed")
                RetryPossible(responseCode);
		        }
		    else
		        {
			    if (responseCode >= K200Ok)
				    {
				    PROFILE_DEBUG1("IETFProfileContext: registration complete")
				    iRetryCounter = 0;
				    iRetryCounterSum = 0;
				    Received2XXRegisterResponse();
		            }
		        }
		    }
        iCurrentState->ResponseReceived(*this, aTransaction);
		}
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::RandomPercent()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TUint CSIPIetfProfileContext::RandomPercent()
	{
	const TInt rand = Math::Rand(iRandomSeed);
	TInt result = 0;
	result = KMaxRandomLimit + (rand%KMaxRandomLimit);
	return result;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::DelayTime()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TUint CSIPIetfProfileContext::DelayTime()
	{
	PROFILE_DEBUG1("CSIPIetfProfileContext::DelayTime")
	TReal res;
	iRetryCounter++;
	iRetryCounterSum++;
	Math::Pow(res,KWaitTimeCoefficient,iRetryCounter);
	TUint respond = res;
	TUint waitTime = KBaseTimeInSec*respond;
	if (waitTime > 1800)
		{
		waitTime = 1800;
		}
	return ((waitTime*RandomPercent())/KRandomDivider);
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::RetryTimerInUse()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CSIPIetfProfileContext::RetryTimerInUse()
	{
	return iRetryTimerUse;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::IsAddressSIPSURIL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CSIPIetfProfileContext::IsAddressSIPSURIL(const TDesC8& aValue) const
	{
	__ASSERT_ALWAYS (aValue.Length() > 0, User::Leave(KErrArgument));
    TUriParser8 uriParser;
    User::LeaveIfError(uriParser.Parse(aValue));
    TPtrC8 sips(SIPStrings::StringF(SipStrConsts::ESips).DesC());
    return (uriParser.Extract(EUriScheme).CompareF(sips) == 0);
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::SetAddressToSIPSURIL()
// -----------------------------------------------------------------------------
//
HBufC8* CSIPIetfProfileContext::SetAddressToSIPSURIL(const TDesC8& aValue)
	{
    TUriParser8 uriParser;
    User::LeaveIfError(uriParser.Parse(aValue));
    CUri8* uri = CUri8::NewLC(uriParser);	
	uri->SetComponentL(
	    SIPStrings::StringF(SipStrConsts::ESips).DesC(),EUriScheme);
	HBufC8* value = uri->Uri().UriDes().AllocL();
	CleanupStack::PopAndDestroy(uri);
	return value;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::SetTlsToSecurityClientL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CSIPIetfProfileContext::SetTlsToSecurityClientL()
	{
	TBool tlsSet = EFalse;
	if(!IsAddressSIPSURIL(iProfile->AOR()) && 
	   iProfile->IsSecurityNegotiationEnabled())
		{
		const TDesC8& proxyAddr = ProxyAddressL();
		if (proxyAddr.Length() > 0)
			{
			if(IsConfiguredOutboundProxySIPURIL(proxyAddr)|| 
			   IsDynamicNumericIPAddress(proxyAddr))
				{
				tlsSet = ETrue;
				}
			}
		}
	return tlsSet;
	}
	
// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::IsDynamicNumericIPAddress()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CSIPIetfProfileContext::IsDynamicNumericIPAddress( const TDesC8& aValue )
	{
	return ( IsProxyResolvingEnabled() && 
		 !( UriUtils::HostType( aValue ) == UriUtils::ETextHost ) );
	}	

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::IsConfiguredOutboundProxySIPURIL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CSIPIetfProfileContext::IsConfiguredOutboundProxySIPURIL( const TDesC8& aValue )
	{
	return ( !IsProxyResolvingEnabled() && !IsAddressSIPSURIL(aValue) );
	}	

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::CreateMsgElementsForUpdateLC
// add SIP headers to REGISTER request
// -----------------------------------------------------------------------------
//
CSIPMessageElements* CSIPIetfProfileContext::CreateMsgElementsForUpdateLC(
    CSIPConcreteProfile& aProfile)
	{
	CSIPMessageElements* elements = CSIPMessageElements::NewLC();
	
	RPointerArray<CSIPHeaderBase> headers;
	CSIPHeaderBase::PushLC(&headers);

	TInt sipHeaderCount = aProfile.SIPHeaders().MdcaCount();
	for (TInt i=0; i < sipHeaderCount; i++)
	    {
	    TPtrC8 headerDes(aProfile.SIPHeaders().MdcaPoint(i));
	    CSIPHeaderBase* header = SIPMessageBuilder::CreateHeaderLC(headerDes);
	    headers.AppendL(header);
	    CleanupStack::Pop(header);
	    }   
	    
	elements->SetUserHeadersL(headers); // An empty array is also allowed
	CleanupStack::Pop(1); // headers
	    
	return elements;
	}

// -----------------------------------------------------------------------------
// CSIPIetfProfileContext::TransportProtocol
// -----------------------------------------------------------------------------
//
RStringF CSIPIetfProfileContext::TransportProtocol(const CUri8& aUri) const
    {
    if (aUri.Uri().Extract(EUriPath).FindF(KTransportUdpParam) >= 0)
        {
        return SIPStrings::StringF(SipStrConsts::EUdp);
        }
    if (aUri.Uri().Extract(EUriPath).FindF(KTransportTcpParam) >= 0)
        {
        return SIPStrings::StringF(SipStrConsts::ETcp);
        }
    if (aUri.Uri().Extract(EUriPath).FindF(KTransportTlsParam) >= 0)
        {
        return SIPStrings::StringF(SipStrConsts::ETLS);
        }
    return SIPStrings::StringF(SipStrConsts::EEmpty);
    }
