// Copyright (c) 2006-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 : CSipConnection.cpp
// Part of : ConnectionMgr
// Version : SIP/5.0
//
#include "CSipConnection.h"
#include "CSipConnectionMgr.h"
#include "SipLogs.h"
#include "CTransportUdp.h"
#include "CTransportTcp.h"
#include "CTransportTls.h"
#include "CIcmpReceiver.h"
#include "MTransactionFinder.h"
#include "CSIPServerResolver.h"
#include "CTcpListeningPoint.h"
#include "COutgoingData.h"
#include "CTcpResSender.h"
#include "MConnectionStateObserver.h"
#include "CLocalAddrResolver.h"
#include "MSigCompController.h"
#include "SipAssert.h"
#include "CConnectionContainer.h"
#include "CNetworkManager.h"
#include "CStateModel.h"
#include "CommonConsts.h"
#include "sipstrings.h"
#include "sipstrconsts.h"
#include "TSIPTransportParams.h"
#include "COwnerSettingsList.h"
#include "siperr.h"
#include "NetworkInfo.h"
#include "sipviaheader.h"
#include "COutgoingRequestQueue.h"
#include "sipuri.h"
#include "uricontainer.h"
#include "siphostport.h"
#include "siprouteheader.h"
#include "sipaddress.h"
#include <uriutils.h>
using namespace CommsDat;
// Max length for an IP address string representation
// (The format is either "d.d.d.d" or "h:h:h:h:h:h:h:h"
// depending on the address family, where "d" is an 8-bit decimal number
// and "h" is a 16-bit hexadecimal number. )
const TUint KMaxAddressLength( 50 );
const TInt CTransportBase::iOffset = _FOFF( CTransportBase, iLink );
// -----------------------------------------------------------------------------
// CSipConnection::NewLC
// -----------------------------------------------------------------------------
//
CSipConnection* CSipConnection::NewLC(
MTransactionFinder& aFinder,
MServerTaFactory& aTaFactory,
MTimerManager& aTimer,
TUint aTOne,
const TSIPTransportParams& aParams,
RSocketServ& aServer,
MSigCompController& aSigCompHandler,
MConnectionStateObserver& aTUNetStatusObserver,
CNetworkManager& aNetworkManager,
MSipConnectionOwner& aOwner,
CNetworkInfo& aNetworkInfo,
CSIPNATTraversalController& aNATTraversal )
{
CSipConnection* self =
new( ELeave ) CSipConnection( aFinder, aTaFactory, aTimer, aTOne,
aParams, aServer, aSigCompHandler,
aTUNetStatusObserver, aNetworkManager,
aOwner, aNetworkInfo, aNATTraversal );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// -----------------------------------------------------------------------------
// CSipConnection::SetOptL
// -----------------------------------------------------------------------------
//
void CSipConnection::SetOptL(
const TSIPTransportParams& aParams,
TUint aOptionName,
TUint aOptionLevel,
const TDesC8& aOption )
{
// Remember opt, it will be used when this caller is using sockets
iSettingsList->AddSettingsL( aParams, aOptionName, aOptionLevel, aOption );
}
// -----------------------------------------------------------------------------
// CSipConnection::SetOptL
// -----------------------------------------------------------------------------
//
void CSipConnection::SetOptL(
const TSIPTransportParams& aParams,
TUint aOptionName,
TUint aOptionLevel,
TInt aOption )
{
// Remember opt, it will be used when this caller is using sockets
iSettingsList->AddSettingsL( aParams, aOptionName, aOptionLevel, aOption );
}
// -----------------------------------------------------------------------------
// CSipConnection::SendL
// -----------------------------------------------------------------------------
//
void CSipConnection::SendL(
const TSIPTransportParams& aParams,
CSIPResponse& aResponse,
TTransactionId aId,
TRequestStatus& aStatus )
{
__SIP_MESSAGE_LOG( "Connection Manager::SendL", aResponse )
iStateModel->SendL( aParams, aResponse, aId, aStatus );
}
// -----------------------------------------------------------------------------
// CSipConnection::SendL
// -----------------------------------------------------------------------------
//
void CSipConnection::SendL(
const TSIPTransportParams& aParams,
CSIPRequest& aRequest,
TBool aForceUDP,
const CUri8* aOutboundProxy,
const TInetAddr& aRemoteAddr,
TRequestStatus& aStatus )
{
__SIP_MESSAGE_LOG( "Connection Manager::SendL", aRequest )
if ( aRemoteAddr.IsMulticast() )
{
TRequestStatus* status = &aStatus;
User::RequestComplete( status, KErrNotSupported );
}
else
{
iStateModel->SendL( aParams,
aRequest,
aForceUDP,
aOutboundProxy,
aRemoteAddr,
aStatus );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::CancelSend
// -----------------------------------------------------------------------------
//
TInt CSipConnection::CancelSend( TRequestStatus &aStatus )
{
TBool cancelled = EFalse;
CTransportBase* listItem = 0;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
cancelled = listItem->CancelSend( aStatus );
if(cancelled)
{
return KErrNone;
}
}
CTcpResponseSender* listsender( NULL );
iTcpSenderListIter.SetToFirst();
while ( ( listsender = iTcpSenderListIter++ ) != 0 )
{
if ( listsender->CancelSend( aStatus ) )
{
return KErrNone;
}
}
if ( iRequestQueue )
{
if ( iRequestQueue->CancelSend( aStatus ) )
{
return KErrNone;
}
}
return KErrNotFound;
}
// -----------------------------------------------------------------------------
// CSipConnection::CancelResponseSend
// -----------------------------------------------------------------------------
//
TInt CSipConnection::CancelResponseSend(
TTransactionId aId,
TBool aCancelAlso2xxResponses )
{
TBool cancelled = EFalse;
CTransportBase* listItem = 0;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
cancelled = listItem->CancelResponseSend( aId, aCancelAlso2xxResponses );
if ( cancelled )
{
return KErrNone;
}
}
return KErrNotFound;
}
// -----------------------------------------------------------------------------
// CSipConnection::TcpDisconnect
// -----------------------------------------------------------------------------
//
void CSipConnection::TcpDisconnect(
const TSIPTransportParams& aParams,
const TInetAddr& aRemoteAddress )
{
CTransportBase* listItem = 0;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->HasRemoteHost( aParams,
aRemoteAddress,
SIPStrings::StringF(SipStrConsts::ETCP) ) )
{
listItem->Disconnect( aRemoteAddress );
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::FreeResources
// -----------------------------------------------------------------------------
//
void CSipConnection::FreeResources(
MSIPNATBindingObserver& aSIPNATBindingObserver )
{
if ( iRequestQueue )
{
iRequestQueue->FreeResources( aSIPNATBindingObserver );
}
// Remove all matching persistent transports
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->Remove( aSIPNATBindingObserver ) )
{
RemoveTransport( listItem );
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::SendToTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::SendToTransportL(
const TSIPTransportParams& aParams,
CSIPResponse& aResponse,
TTransactionId aId,
TRequestStatus &aStatus )
{
CTransportBase* transport = 0;
CSIPViaHeader* viaHeader = TopViaHeader( &aResponse );
if ( viaHeader )
{
TBool isPortPresent = viaHeader->SentByHostPort().HasPort();
if (isPortPresent)
{
TUint sentByPort = viaHeader->SentByHostPort().Port();
if ((sentByPort > KMaxPortValue) || (sentByPort < KMinPortValue))
{
TRequestStatus* status = &aStatus;
__SIP_LOG( "Sent-by port is topmost viaheader is invalid, dropping response" )
User::RequestComplete( status, CSipConnectionMgr::EPortUnreachable );
return;
}
}
}
TBool isTransportUdp = IsTransportUdp( &aResponse );
transport = FindTransportL( aParams, &aResponse, aId, !isTransportUdp );
if ( !isTransportUdp && !transport )
{
// When connected transport is used, there might be several connections
// with same remote address, in that case we had to search through all
// transports for matching the ta id. At this point any matching
// transport wasn't found, now we can take also remote address in count.
transport = FindTransportL( aParams, &aResponse, aId, EFalse );
if ( !transport )
{
// If there's saved settings regarding remote address, use them
// instead of address passed from upper layers (probably only the
// port differs)
TInetAddr addrFromResponse;
const TInetAddr* address;
const TInetAddr* savedAddr =
iSettingsList->SavedRemoteAddr( aParams.TransportId() );
if ( savedAddr )
{
address = savedAddr;
}
else
{
CTransportBase* listItem;
if ( !iList.IsEmpty() )
{
iListIter.SetToFirst();
listItem = iListIter;
listItem->GetAddrFromResponseL( aParams,
aResponse,
addrFromResponse );
}
address = &addrFromResponse;
}
if ( !address->IsWildAddr() )
{
CreateConnectedTransportPointL( aParams, aResponse, *address );
transport = FindTransportL( aParams, &aResponse, aId, EFalse );
}
}
}
if ( transport )
{
transport->Send( aParams, aResponse, aId, aStatus );
}
else
{
TRequestStatus* stat = &aStatus;
User::RequestComplete( stat, KErrNotFound );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::SendToTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::SendToTransportL(
const TSIPTransportParams& aParams,
CSIPRequest& aRequest,
TBool aForceUDP,
const CUri8* aOutboundProxy,
const TInetAddr& aAddr,
TRequestStatus &aStatus )
{
TUint origTransport =
UpdateTransportIfNeededL( aRequest, aParams, aForceUDP, aAddr );
// If there's saved settings regarding remote address, use them instead of
// address passed from upper layers (probably only the port differs)
const TInetAddr* address =
iSettingsList->SavedRemoteAddr( aParams.TransportId() );
if ( !address )
{
address = &aAddr;
}
TInetAddr localAddr;
GetLocalAddrL( localAddr, address );
iRequestQueue->NATTraverseL( aParams,
aRequest,
aForceUDP,
*address,
aOutboundProxy,
origTransport,
aStatus,
localAddr );
}
// -----------------------------------------------------------------------------
// CSipConnection::ContinueSendToTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::ContinueSendToTransportL(
const TSIPTransportParams& aParams,
CSIPRequest& aRequest,
TBool aForceUDP,
const TInetAddr& aRemoteAddr,
TUint aLocalPort,
TUint aOrigTransport,
TRequestStatus& aStatus,
TBool aPublicAddrResolved )
{
__ASSERT_ALWAYS( IsConnectionActive(), User::Leave( KErrNotReady ) );
CTransportBase* transport =
FindTransportL( aParams, &aRequest, aRemoteAddr, aLocalPort );
if ( transport != 0 )
{
aStatus = KRequestPending;
transport->Send( aParams,
aRequest,
aForceUDP,
aRemoteAddr,
aOrigTransport,
aStatus,
aPublicAddrResolved );
}
else
{
if ( aRequest.HasHeader( SIPStrings::StringF(SipStrConsts::EViaHeader) ) )
{
if ( IsTransportUdp( &aRequest ) )
{
AddUdpListenerL(
TSIPTransportParams( KDefaultOwnerId, iIapId ),
KDefaultSipPort );
}
else
{
CreateConnectedTransportPointL( aParams, aRequest, aRemoteAddr );
}
transport = FindTransportL( aParams, &aRequest, aRemoteAddr );
if ( transport )
{
aStatus = KRequestPending;
transport->Send( aParams,
aRequest,
aForceUDP,
aRemoteAddr,
aOrigTransport,
aStatus,
aPublicAddrResolved );
}
else
{
TRequestStatus* stat = &aStatus;
User::RequestComplete( stat, KErrNotReady );
}
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::RequestFailed
// -----------------------------------------------------------------------------
//
void CSipConnection::RequestFailed( TRequestStatus& aStatus, TInt aError )
{
if ( aStatus == KRequestPending )
{
TRequestStatus* status = &aStatus;
User::RequestComplete( status, aError );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::GetUdpSocketL
// -----------------------------------------------------------------------------
//
RSocket& CSipConnection::GetUdpSocketL(
const TSIPTransportParams& aParams,
const TInetAddr& aRemoteAddr,
TUint& aLocalPort,
MSocketUsagePermissionObserver* aObserver,
TBool& aPermissionToUse )
{
CTransportBase* transport =
FindTransport( aParams,
SIPStrings::StringF( SipStrConsts::EUDP ),
aRemoteAddr,
aLocalPort,
EFalse );
if ( !transport )
{
if ( !aLocalPort )
{
aLocalPort = iSettingsList->GetPrivatePortL( aParams );
}
transport = AddUdpListenerL( aParams, aLocalPort, ETrue );
}
RSocket* udpSocket =
transport->AcquireUdpSocket( aObserver, aRemoteAddr, aPermissionToUse );
__ASSERT_ALWAYS( udpSocket, User::Leave( KErrNotFound ) );
return *udpSocket;
}
// -----------------------------------------------------------------------------
// CSipConnection::UdpSocketFree
// -----------------------------------------------------------------------------
//
void CSipConnection::UdpSocketFree(
const TSIPTransportParams& aParams,
const TInetAddr& aRemoteAddr,
TUint aLocalPort,
MSocketUsagePermissionObserver* aObserver,
RSocket& aSocket )
{
CTransportBase* transport =
FindTransport( aParams,
SIPStrings::StringF( SipStrConsts::EUDP ),
aRemoteAddr,
aLocalPort,
EFalse );
if ( transport )
{
transport->UdpSocketReleased( aObserver, aSocket );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::UpdateTransportIfNeededL
// -----------------------------------------------------------------------------
//
TUint CSipConnection::UpdateTransportIfNeededL(
CSIPMessage& aMessage,
const TSIPTransportParams& aParams,
TBool aForceUDP,
const TInetAddr& aAddr )
{
TUint origTransport = TransportProtocolL( aMessage );
CSIPViaHeader* via = TopViaHeader( &aMessage );
if ( via )
{
TBool tlsForced =
iSettingsList->HasSavedTLSTransportInfo( aParams.TransportId() );
if ( tlsForced && origTransport != KProtocolTls )
{
via->SetTransportL( SIPStrings::StringF(SipStrConsts::ETLS) );
// Upper layer may give incorrect port information in some
// situations when TLS is in use, ensure that at least
// default TLS port is used.
iSettingsList->SaveTLSRemoteL( aParams, aAddr );
}
else if ( origTransport == KProtocolInetUdp && !aForceUDP &&
( aMessage.EncodedHeaderPartLengthL() +
aMessage.Content().Length() ) > KMaxUdpMessageSize )
{
via->SetTransportL( SIPStrings::StringF(SipStrConsts::ETCP) );
}
else
{
}
}
return origTransport;
}
// -----------------------------------------------------------------------------
// CSipConnection::CreateConnectedTransportPointL
// -----------------------------------------------------------------------------
//
void CSipConnection::CreateConnectedTransportPointL(
const TSIPTransportParams& aParams,
CSIPMessage& aMessage,
const TInetAddr& aAddress )
{
TUint protocol = TransportProtocolL( aMessage );
switch ( protocol )
{
case KProtocolInetTcp:
{
CreateTcpTransportPointL( aParams, aAddress );
break;
}
case KProtocolTls:
{
CreateTlsTransportPointL( aParams, aAddress );
//Check if the SIP message is request.Below code sets the
//domain name into CTransportTls object which will be later
//used in domain name matching during TLS Negotiation
HBufC8 *domainName = NULL;
CTransportTls *transport;
if(aMessage.IsRequest())
{
//If the SIP request has Route header then the host part will be extracted
//from the Route header
const RStringF route = SIPStrings::StringF(SipStrConsts::ERouteHeader);
if(aMessage.HasHeader(route))
{
TSglQueIter<CSIPHeaderBase> iter = aMessage.Headers( route );
iter.SetToFirst();
CSIPHeaderBase* header = iter;
if ( header )
{
CSIPRouteHeader* routeHeader = static_cast<CSIPRouteHeader*>( header );
domainName = routeHeader->SIPAddress().URI().SIPURI()->HostPort().Host().AllocL();
}
}
else
{
//If the Route header is absent from the SIP Request, request-line
//gets preference and host part is extracted from the request-line
CSIPRequest &request = static_cast<CSIPRequest&>(aMessage ) ;
domainName = request.RequestURI()->SIPURI()->HostPort().Host().AllocL();
}
}
else
{
//Message is response. Host part will be extracted from the top
//Via header
CSIPViaHeader* viaHeader = TopViaHeader( &aMessage );
domainName = viaHeader->SentByHostPort().Host().AllocL();
}
transport = static_cast<CTransportTls*>(FindTransport( aParams,
SIPStrings::StringF( SipStrConsts::ETLS ),
aAddress));
//If the domain name is of type "Text", set the domain name for the
//TLS object.
if ( ( UriUtils::HostType( *domainName ) == UriUtils::ETextHost ))
transport->SetDomainNameL(domainName->Des());
delete domainName;
break;
}
default:
{
User::Leave( KErrArgument );
break;
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::CreateTcpTransportPointL
// -----------------------------------------------------------------------------
//
void CSipConnection::CreateTcpTransportPointL(
const TSIPTransportParams& aParams,
const TInetAddr& aAddress )
{
// Leave if tcp connection with remote address exists already
CTransportBase* listItem = 0;
iListIter.SetToFirst();
while( ( listItem = iListIter++ ) != 0 )
{
if( listItem->HasRemoteHost( aParams,
aAddress,
SIPStrings::StringF(SipStrConsts::ETCP) ) )
{
User::Leave( KErrSIPTransportFailure );
}
}
CTransportBase* transport =
CTransportTcp::NewLC(
iServer, iFinder, iTaFactory,
*this, iTimer, aParams, aAddress, iTOne,
*iServerResolver, Connection(), iSigCompHandler,
iSettingsList->SavedLocalSendPort( aParams.TransportId() ),
iNetworkInfo, *iSettingsList, iNATTraversal );
AddTransportL( transport );
CleanupStack::Pop( transport );
}
// -----------------------------------------------------------------------------
// CSipConnection::CreateTlsTransportPointL
// -----------------------------------------------------------------------------
//
void CSipConnection::CreateTlsTransportPointL(
const TSIPTransportParams& aParams,
const TInetAddr& aAddress )
{
// Leave if tcp connection with remote address exists already
CTransportBase* listItem = 0;
iListIter.SetToFirst();
while( ( listItem = iListIter++ ) != 0 )
{
if( listItem->HasRemoteHost( aParams,
aAddress,
SIPStrings::StringF(SipStrConsts::ETLS) ) )
{
User::Leave( KErrSIPTransportFailure );
}
}
CTransportBase* transport =
CTransportTls::NewLC(
iServer, iFinder, iTaFactory,
*this, iTimer, aParams, aAddress, iTOne,
*iServerResolver, Connection(), iSigCompHandler,
iNetworkInfo, *iSettingsList, iNATTraversal );
AddTransportL( transport );
CleanupStack::Pop( transport );
}
// -----------------------------------------------------------------------------
// CSipConnection::IsTransportUdp
// -----------------------------------------------------------------------------
//
TBool CSipConnection::IsTransportUdp( CSIPMessage* aMessage )
{
CSIPViaHeader* via = TopViaHeader( aMessage );
if( via )
{
if( via->Transport() == SIPStrings::StringF(SipStrConsts::EUDP) )
{
return ETrue;
}
}
return EFalse;
}
// -----------------------------------------------------------------------------
// CSipConnection::TransportProtocolL
// -----------------------------------------------------------------------------
//
TUint CSipConnection::TransportProtocolL( CSIPMessage& aMessage )
{
CSIPViaHeader* via = TopViaHeader( &aMessage );
__ASSERT_ALWAYS( via, User::Leave( KErrNotFound ) );
RStringF transport = via->Transport();
if ( transport == SIPStrings::StringF( SipStrConsts::EUDP ) )
{
return KProtocolInetUdp;
}
else if ( transport == SIPStrings::StringF( SipStrConsts::ETCP ) )
{
return KProtocolInetTcp;
}
else if ( transport == SIPStrings::StringF( SipStrConsts::ETLS ) )
{
return KProtocolTls;
}
else
{
User::Leave( KErrNotSupported );
}
return 0;
}
// -----------------------------------------------------------------------------
// CSipConnection::ResetTransportsL
// -----------------------------------------------------------------------------
//
void CSipConnection::ResetTransportsL()
{
RemoveAllTransports();
TSIPTransportParams defaultParams( KDefaultOwnerId, iIapId );
AddTcpListenerL( defaultParams, KDefaultSipPort );
AddUdpListenerL( defaultParams, KDefaultSipPort );
}
// -----------------------------------------------------------------------------
// CSipConnection::IsInList
// -----------------------------------------------------------------------------
//
TBool CSipConnection::IsInList( CTransportBase* aTransport )
{
if( aTransport )
{
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if( listItem == aTransport )
{
return ETrue;
}
}
}
return EFalse;
}
// -----------------------------------------------------------------------------
// CSipConnection::AddTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::AddTransportL( CTransportBase* aTransport )
{
if( aTransport )
{
if( !IsInList( aTransport ) )
{
iList.AddLast( *aTransport );
}
else
{
User::Leave( KErrAlreadyExists );
}
}
else
{
User::Leave( KErrGeneral );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::RemoveTransport
// -----------------------------------------------------------------------------
//
TInt CSipConnection::RemoveTransport( CTransportBase* aTransport )
{
if( IsInList( aTransport ) )
{
iList.Remove( *aTransport );
delete aTransport;
return KErrNone;
}
else
{
return KErrNotFound;
}
}
// -----------------------------------------------------------------------------
// CSipConnection::RemoveAllTransports
// -----------------------------------------------------------------------------
//
void CSipConnection::RemoveAllTransports()
{
CTransportBase* listItem( NULL );
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
iList.Remove( *listItem );
delete listItem;
}
}
// -----------------------------------------------------------------------------
// CSipConnection::FindTransportL
// -----------------------------------------------------------------------------
//
CTransportBase* CSipConnection::FindTransportL(
const TSIPTransportParams& aParams,
CSIPMessage* aMessage,
TTransactionId aId,
TBool aIsStrict )
{
iListIter.SetToFirst();
CTransportBase* listItem = NULL;
while ( ( listItem = iListIter++ ) != 0 )
{
if( listItem->HandleL( aParams, aMessage, aId, aIsStrict ) )
{
return listItem;
}
}
return 0;
}
// -----------------------------------------------------------------------------
// CSipConnection::FindTransportL
// -----------------------------------------------------------------------------
//
CTransportBase* CSipConnection::FindTransportL(
const TSIPTransportParams& aParams,
CSIPMessage* aMessage,
const TInetAddr& aRemoteAddr,
TUint aLocalPort,
TBool aIsStrict )
{
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->HandleL( aParams,
aMessage,
aRemoteAddr,
aLocalPort,
aIsStrict ) )
{
return listItem;
}
}
return 0;
}
// -----------------------------------------------------------------------------
// CSipConnection::FindTransportL
// -----------------------------------------------------------------------------
//
CTransportBase* CSipConnection::FindTransport(
const TSIPTransportParams& aParams,
RStringF aProtocol,
const TInetAddr& aRemoteAddr,
TUint aLocalPort,
TBool aIsStrict )
{
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->HandleMessage( aParams,
aProtocol,
aRemoteAddr,
aLocalPort,
aIsStrict ) )
{
return listItem;
}
}
return 0;
}
// -----------------------------------------------------------------------------
// CSipConnection::RemoveTcpSender
// -----------------------------------------------------------------------------
//
void CSipConnection::RemoveTcpSender( CTcpResponseSender* aThis )
{
if ( !iTcpSenderList.IsEmpty() )
{
iTcpSenderList.Remove( *aThis );
delete aThis;
}
}
// -----------------------------------------------------------------------------
// CSipConnection::RemoveAllTcpSender
// -----------------------------------------------------------------------------
//
void CSipConnection::RemoveAllTcpSender()
{
CTcpResponseSender* listItem( NULL );
iTcpSenderListIter.SetToFirst();
while ( ( listItem = iTcpSenderListIter++ ) != 0 )
{
iTcpSenderList.Remove( *listItem );
delete listItem;
}
}
// -----------------------------------------------------------------------------
// CSipConnection::TcpConnected
// -----------------------------------------------------------------------------
//
void CSipConnection::TcpConnected( const TInetAddr& aAddr )
{
CTcpResponseSender* listItem( NULL );
iTcpSenderListIter.SetToFirst();
while ( ( listItem = iTcpSenderListIter++ ) != 0 )
{
listItem->Connected( aAddr );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::ReRouteL
// -----------------------------------------------------------------------------
//
void CSipConnection::ReRouteL( TUint aProtocol, COutgoingData* aData )
{
__ASSERT_ALWAYS( aData, User::Leave( KErrArgument ) );
const TSIPTransportParams& tpParams = aData->TransportParams();
if ( aProtocol == KProtocolInetTcp &&
aData->Message().IsRequest() )
{
CSIPViaHeader* via = TopViaHeader( &aData->Message() );
if(via)
{
via->SetTransportL( SIPStrings::StringF(SipStrConsts::ETCP) );
}
// Public address resolved value can be passed as true, since
// at this point all necessary via and contact header updates
// have been done (i.e. no need to update).
ContinueSendToTransportL(
tpParams,
static_cast<CSIPRequest&>( aData->Message() ),
aData->ForceUDP(),
aData->Address(),
0,
aData->OrigTransport(),
*aData->Status(),
ETrue );
delete aData;
return;
}
if ( aProtocol == KProtocolInetTcp )
{
CTcpResponseSender* tcpsender( NULL );
while ( (tcpsender = iTcpSenderListIter++ ) != 0 )
{
if ( tcpsender->IsInProgress( *aData ) )
{
tcpsender->ConnectionFailedL();
delete aData;
return;
}
}
tcpsender =
new ( ELeave ) CTcpResponseSender( tpParams,
*iServerResolver,
*this );
iTcpSenderList.AddLast( *tcpsender );
tcpsender->ResolveL( *aData );
tcpsender->SetData( aData );
}
if ( aProtocol == KProtocolInetUdp &&
( aData->Message().EncodedHeaderPartLengthL() +
aData->Message().Content().Length() ) > KMaxMessageLength )
{
TRequestStatus* stat = aData->Status();
User::RequestComplete( stat, KErrCouldNotConnect );
delete aData;
return;
}
if ( aProtocol == KProtocolInetUdp )
{
CSIPViaHeader* via = TopViaHeader( &aData->Message() );
if ( via )
{
via->SetTransportL( SIPStrings::StringF(SipStrConsts::EUDP) );
}
CSender* send = GetSender( tpParams, aProtocol, aData->Address() );
if ( send )
{
send->SendL( aData );
}
else
{
AddUdpListenerL(
TSIPTransportParams( KDefaultOwnerId, iIapId ),
KDefaultSipPort );
send = GetSender( tpParams, aProtocol, aData->Address() );
if ( send )
{
send->SendL( aData );
}
else
{
TRequestStatus* stat = aData->Status();
User::RequestComplete( stat, KErrCouldNotConnect );
delete aData;
}
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::GetSender
// -----------------------------------------------------------------------------
//
CSender* CSipConnection::GetSender(
const TSIPTransportParams& aParams,
TUint aProtocol,
const TInetAddr& aAddr )
{
CTransportBase* listItem;
iListIter.SetToFirst();
CSender* sender = NULL;
while( ( ( listItem = iListIter++ ) != 0 ) && !sender )
{
sender = listItem->Sender( aParams, aProtocol, aAddr );
}
return sender;
}
// -----------------------------------------------------------------------------
// CSipConnection::AddListenerL
// -----------------------------------------------------------------------------
//
void CSipConnection::AddListenerL(
const TSIPTransportParams& aParams,
TUint aProtocol,
TUint aPort )
{
AddTcpListenerL( aParams, aPort );
if( aProtocol != KProtocolInetTcp )
{
AddUdpListenerL( aParams, aPort );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::AddTcpListenerL
// -----------------------------------------------------------------------------
//
void CSipConnection::AddTcpListenerL(
const TSIPTransportParams& aParams,
TUint aPort,
TBool aIsReserved )
{
if( !IsListened( KProtocolInetTcp, aPort ) )
{
CTransportBase* transportTcp =
CTcpListeningPoint::NewLC( iServer, iFinder, iTaFactory, *this,
iTimer, aPort, iTOne, *iServerResolver,
Connection(), iSigCompHandler,
iNetworkInfo, *iSettingsList, aParams,
iNATTraversal );
AddTransportL( transportTcp );
CleanupStack::Pop( transportTcp );
transportTcp->WaitL();
}
else
{
__ASSERT_ALWAYS( !aIsReserved, User::Leave( KErrSIPTransportFailure ) );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::AddUdpListenerL
// -----------------------------------------------------------------------------
//
CTransportBase* CSipConnection::AddUdpListenerL(
const TSIPTransportParams& aParams,
TUint aPort,
TBool aIsReserved,
TBool aOnlyForReceiving )
{
CTransportBase* transport( NULL );
if( !IsListened( KProtocolInetUdp, aPort ) )
{
transport =
CTransportUdp::NewLC( iServer, aPort, iFinder,
iTaFactory, *this, iTimer, *iServerResolver,
Connection(), iSigCompHandler, iTOne,
iNetworkInfo, *iSettingsList, aParams,
iNATTraversal, aOnlyForReceiving );
AddTransportL( transport );
CleanupStack::Pop( transport );
transport->WaitL();
}
else
{
__ASSERT_ALWAYS( !aIsReserved, User::Leave( KErrSIPTransportFailure ) );
}
return transport;
}
// -----------------------------------------------------------------------------
// CSipConnection::AddTcpListenerUserL
// -----------------------------------------------------------------------------
//
void CSipConnection::AddTcpListenerUserL(
const TSIPTransportParams& aOldParams,
const TSIPTransportParams& aParams,
TUint aReceivePort )
{
CTransportBase* listItem( NULL );
iListIter.SetToFirst();
TBool added( EFalse );
while ( ( listItem = iListIter++ ) != 0 && !added )
{
if( listItem->Handle( aOldParams.TransportId() ) &&
listItem->ProtocolType() == KProtocolInetTcp )
{
added = listItem->AddUserL( aParams, aReceivePort );
}
}
if ( !added )
{
User::Leave( KErrNotFound );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::AddUdpListenerUserL
// -----------------------------------------------------------------------------
//
void CSipConnection::AddUdpListenerUserL(
const TSIPTransportParams& aOldParams,
const TSIPTransportParams& aParams,
TUint aReceivePort )
{
CTransportBase* listItem( NULL );
iListIter.SetToFirst();
TBool added( EFalse );
while ( ( listItem = iListIter++ ) != 0 && !added )
{
if( listItem->Handle( aOldParams.TransportId() ) &&
listItem->ProtocolType() == KProtocolInetUdp )
{
added = listItem->AddUserL( aParams, aReceivePort );
}
}
if ( !added )
{
User::Leave( KErrNotFound );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::IsListened
// -----------------------------------------------------------------------------
//
TBool CSipConnection::IsListened( TInt aProtocol, TUint aPort )
{
CTransportBase* listItem( NULL );
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if( listItem->IsWaiting( aProtocol, aPort ) )
{
return ETrue;
}
}
return EFalse;
}
// -----------------------------------------------------------------------------
// CSipConnection::CancelAllRequests
// -----------------------------------------------------------------------------
//
void CSipConnection::CancelAllRequests( CSIPConnection::TState aReason )
{
CTransportBase* listItem( NULL );
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
listItem->CancelAllRequests( aReason );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::IcmpError
// -----------------------------------------------------------------------------
//
void CSipConnection::IcmpError( const TInetAddr& aAddress )
{
TRAP_IGNORE( NotifyIcmpErrorL( aAddress ) )
}
// -----------------------------------------------------------------------------
// CSipConnection::GetByURIL
// -----------------------------------------------------------------------------
//
void CSipConnection::GetByURIL( const TSIPTransportParams& aParams,
const CURIContainer& aURI,
RPointerArray<MSIPResolvingResult>& aResult,
MSIPServerResolverObserver* aObserver )
{
__ASSERT_ALWAYS( iServerResolver, User::Leave( KErrNotReady ) );
// Have to do const cast in order to get binding observer
MSIPNATBindingObserver* bindingObserver =
const_cast<TSIPTransportParams&>( aParams ).NATBindingObserver();
TBool persistentConnectionFound( EFalse );
TInetAddr* remoteAddr = 0;
TUint protocol = 0;
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 && !persistentConnectionFound )
{
protocol = listItem->ProtocolType();
remoteAddr = listItem->PersistentRemoteAddr( bindingObserver );
persistentConnectionFound =
( remoteAddr &&
( protocol == KProtocolInetTcp || protocol == KProtocolTls ) );
}
TBool skipNaptrAndSrv = aParams.SkipNaptrAndSrv();
if ( persistentConnectionFound )
{
CURIContainer* uriContainer = CURIContainer::NewLC( aURI );
UpdateURIL( *uriContainer, *remoteAddr, protocol );
iServerResolver->GetByURIL( *uriContainer, skipNaptrAndSrv,
aResult, aObserver );
CleanupStack::PopAndDestroy( uriContainer );
return;
}
iServerResolver->GetByURIL( aURI, skipNaptrAndSrv, aResult, aObserver );
}
// -----------------------------------------------------------------------------
// CSipConnection::CancelGetByUri
// -----------------------------------------------------------------------------
//
void CSipConnection::CancelGetByUri( MSIPServerResolverObserver* aObserver )
{
if( iServerResolver )
{
iServerResolver->Cancel( aObserver );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::GetLocalAddress
// -----------------------------------------------------------------------------
//
TInt CSipConnection::GetLocalAddress( TInetAddr& aAddr )
{
if ( !iLocalAddrResolver )
{
return KErrNotReady;
}
TRAPD( err, GetLocalAddrL( aAddr, NULL ) );
return err;
}
// -----------------------------------------------------------------------------
// CSipConnection::IsLocalAddr
// -----------------------------------------------------------------------------
//
TBool CSipConnection::IsLocalAddr( TInetAddr& aAddr ) const
{
return iLocalAddrResolver->IsLocalAddr( aAddr );
}
// -----------------------------------------------------------------------------
// CSipConnection::GetLocalAddrL
// -----------------------------------------------------------------------------
//
void CSipConnection::GetLocalAddrL(
TInetAddr& aAddr,
const TInetAddr* aNextHop )
{
if( iLocalAddrResolver )
{
iLocalAddrResolver->RefreshLocalAddressesL();
FillWithMatchingAddrFamily( aAddr, aNextHop );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::GetLocalIPAddr
// -----------------------------------------------------------------------------
//
TBool CSipConnection::GetLocalIPAddr( TUint aFamily, TInetAddr& aAddr )
{
TBool found( EFalse );
if( iLocalAddrResolver )
{
if ( aFamily == KAfInet )
{
if ( !iLocalAddrResolver->IPv4Addr().IsUnspecified() )
{
aAddr = iLocalAddrResolver->IPv4Addr();
found = ETrue;
}
}
else
{
if ( !iLocalAddrResolver->IPv6Addr().IsUnspecified() )
{
aAddr = iLocalAddrResolver->IPv6Addr();
found = ETrue;
}
}
}
return found;
}
// -----------------------------------------------------------------------------
// CSipConnection::FillWithMatchingAddrFamily
// -----------------------------------------------------------------------------
//
void CSipConnection::FillWithMatchingAddrFamily(
TInetAddr& aAddr,
const TInetAddr* aNextHop )
{
__SIP_ADDR_LOG("CSipConnection::FillWithMatchingAddrFamily: local IPv6 addr",
iLocalAddrResolver->IPv6Addr())
__SIP_ADDR_LOG("CSipConnection::FillWithMatchingAddrFamily: local IPv4 addr",
iLocalAddrResolver->IPv4Addr())
if ( !iLocalAddrResolver->IPv4Addr().IsUnspecified() )
{
aAddr = iLocalAddrResolver->IPv4Addr();
}
else
{
aAddr = iLocalAddrResolver->IPv6Addr();
}
if ( aNextHop )
{
__SIP_ADDR_LOG("CSipConnection::FillWithMatchingAddrFamily: next hop addr",
*aNextHop)
if ( aNextHop->Address() ) // Contains IPv4 address
{
__SIP_INT_LOG1("CSipConnection::FillWithMatchingAddrFamily: next hop family",
KAfInet)
if ( iLocalAddrResolver->IPv4Addr().IsUnspecified() &&
( aAddr.IsV4Compat() || aAddr.IsV4Mapped() ) )
{
aAddr.ConvertToV4();
}
}
else
{
__SIP_INT_LOG1("CSipConnection::FillWithMatchingAddrFamily: next hop family",
KAfInet6)
if ( iLocalAddrResolver->IPv6Addr().IsUnspecified() )
{
aAddr = iLocalAddrResolver->IPv4Addr();
aAddr.ConvertToV4Mapped();
}
else
{
aAddr = iLocalAddrResolver->IPv6Addr();
}
}
}
__SIP_ADDR_LOG("CSipConnection::FillWithMatchingAddrFamily returns",aAddr)
}
// -----------------------------------------------------------------------------
// CSipConnection::DecreaseUserCount
// -----------------------------------------------------------------------------
//
TInt CSipConnection::DecreaseUserCount( const TSIPTransportParams& aParams )
{
__SIP_ASSERT_RETURN_VALUE( iUserCount > 0, KErrUnderflow );
iSettingsList->RemoveSettings( aParams );
// Remove all related transports, default transports are not removed
//
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->Remove( aParams ) )
{
RemoveTransport( listItem );
}
}
iUserCount--;
return iUserCount;
}
// -----------------------------------------------------------------------------
// CSipConnection::IncreaseUserCount
// -----------------------------------------------------------------------------
//
void CSipConnection::IncreaseUserCount()
{
iUserCount++;
}
// -----------------------------------------------------------------------------
// CSipConnection::Handle
// -----------------------------------------------------------------------------
//
TBool CSipConnection::Handle( TUint32 aIapId ) const
{
return ( aIapId == iIapId );
}
// -----------------------------------------------------------------------------
// CSipConnection::IapId
// -----------------------------------------------------------------------------
//
TUint32 CSipConnection::IapId() const
{
return iIapId;
}
// -----------------------------------------------------------------------------
// CSipConnection::ReserveTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::ReserveTransportL(
const TSIPTransportParams& aOldTransportParams,
const TSIPTransportParams& aTransportParams,
TUint aLocalSendPort,
TUint aLocalReceivePort,
const TInetAddr& aRemoteAddr,
TUint aRemoteSendPort )
{
// First reserve ports and save information about transport.
// - will leave with KErrSIPTransportFailure if some of the ports are
// already reserved (if reservations for old transport id exist already,
// duplicate reservations are allowed).
if ( !iSettingsList->SaveTransportInfoL( aOldTransportParams,
aTransportParams,
aLocalSendPort,
aLocalReceivePort,
aRemoteAddr,
aRemoteSendPort ) )
{
// Because no previous settings matching aOldTransportParams were found
// also listeners don't exist yet, create them
//
AddTcpListenerL( aTransportParams, aLocalReceivePort, ETrue );
AddUdpListenerL( aTransportParams, aLocalReceivePort, ETrue, ETrue );
}
else
{
// For existing tcp and udp listeners, add knowledge about second user
//
AddTcpListenerUserL( aOldTransportParams,
aTransportParams,
aLocalReceivePort );
AddUdpListenerUserL( aOldTransportParams,
aTransportParams,
aLocalReceivePort );
}
AddUdpListenerL( aTransportParams, aLocalSendPort, ETrue );
// TCP connection for outgoing requests is not created until sending occurs
}
// -----------------------------------------------------------------------------
// CSipConnection::ReserveTLSTransportL
// -----------------------------------------------------------------------------
//
void CSipConnection::ReserveTLSTransportL(
TSIPTransportParams& aTransportParams )
{
iSettingsList->SaveTLSTransportInfoL( aTransportParams );
}
// -----------------------------------------------------------------------------
// CSipConnection::RemoveTransport
// -----------------------------------------------------------------------------
//
TBool CSipConnection::RemoveReservedTransport(
TUint32 aTransportId,
MSIPTransportRemovalObserver* aRemovalObserver,
TInt& aNumAsyncRemovals )
{
// First remove corresponding settings
if( !iSettingsList->RemoveSettings( aTransportId ) )
{
return EFalse;
}
// If some settings were removed there is also transports which has to
// be removed
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
if ( listItem->Handle( aTransportId ) )
{
// Remove call will remove everything inside the transport related
// to the transport id and if Remove() returns ETrue, transport
// can be removed completely (if asynchronous shutdown is
// not required)
TBool lastUser = listItem->Remove( aTransportId );
if ( listItem->Shutdown( aTransportId, aRemovalObserver ) )
{
// Caller has to wait asynchronous completion of transport
// removal
aNumAsyncRemovals++;
}
else if ( lastUser )
{
RemoveTransport( listItem );
}
else
{
}
}
}
return ETrue;
}
// -----------------------------------------------------------------------------
// CSipConnection::Match
// -----------------------------------------------------------------------------
//
TBool CSipConnection::Match( const TDesC8& aAddress )
{
TInetAddr address;
GetLocalAddress( address );
TBuf16< KMaxAddressLength > addressout16;
TBuf8< KMaxAddressLength > addressout8;
address.Output( addressout16 );
addressout8.Copy( addressout16 );
return ( addressout8 == aAddress );
}
// -----------------------------------------------------------------------------
// CSipConnection::CreateTransportResourcesL
// -----------------------------------------------------------------------------
//
void CSipConnection::CreateTransportResourcesL()
{
__SIP_LOG( "CreateTransportResourcesL" )
//Resources must not exist already
__SIP_ASSERT_LEAVE( !iIcmpReceiver, KErrAlreadyExists );
__SIP_ASSERT_LEAVE( !iServerResolver, KErrAlreadyExists );
__SIP_ASSERT_LEAVE( !iLocalAddrResolver, KErrAlreadyExists );
iIcmpReceiver = CIcmpReceiver::NewL( *this, iServer );
iServerResolver = CSIPServerResolver::NewL( iServer, Connection() );
iLocalAddrResolver =
CLocalAddrResolver::NewL( iServer, Connection());
iRequestQueue = COutgoingRequestQueue::NewL( *this,
iNATTraversal,
Connection(),
iIapId );
}
// -----------------------------------------------------------------------------
// CSipConnection::CreateDefaultTransportsL
// -----------------------------------------------------------------------------
//
void CSipConnection::CreateDefaultTransportsL()
{
TSIPTransportParams defaultParams( KDefaultOwnerId, iIapId );
if ( !IsListened( KProtocolInetTcp, KDefaultSipPort ) )
{
AddTcpListenerL( defaultParams, KDefaultSipPort );
}
if ( !IsListened( KProtocolInetUdp, KDefaultSipPort ) )
{
AddUdpListenerL( defaultParams, KDefaultSipPort );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::ReleaseTransportResources
// -----------------------------------------------------------------------------
//
void CSipConnection::ReleaseTransportResources( TBool aReleaseAllResources )
{
__SIP_LOG( "ReleaseTransportResources" )
delete iIcmpReceiver;
iIcmpReceiver = NULL;
RemoveAllTransports();
RemoveAllTcpSender();
delete iServerResolver;
iServerResolver = NULL;
delete iLocalAddrResolver;
iLocalAddrResolver = NULL;
delete iRequestQueue;
iRequestQueue = NULL;
if ( aReleaseAllResources )
{
#if ( !defined( __WINS__ ) && !defined( __WINSCW__ ) )
// In HW RConnection must be closed when network coverage is lost
CloseConnection();
#endif
}
}
// -----------------------------------------------------------------------------
// CSipConnection::DoTransportResourcesExist
// -----------------------------------------------------------------------------
//
TBool CSipConnection::DoTransportResourcesExist() const
{
return ( iIcmpReceiver != 0 &&
iServerResolver != 0 &&
iLocalAddrResolver != 0 &&
iRequestQueue != 0 );
}
// -----------------------------------------------------------------------------
// CSipConnection::OpenConnection
// -----------------------------------------------------------------------------
//
TInt CSipConnection::OpenConnection()
{
return iConnection->OpenConnection( iIapId, iServer );
}
// -----------------------------------------------------------------------------
// CSipConnection::CloseConnection
// -----------------------------------------------------------------------------
//
void CSipConnection::CloseConnection()
{
if ( iConnection )
{
iConnection->CloseConnection();
}
}
// -----------------------------------------------------------------------------
// CSipConnection::ResolveLocalAddress
// -----------------------------------------------------------------------------
//
void CSipConnection::ResolveLocalAddress( TInetAddr& aAddress )
{
GetLocalAddress( aAddress );
}
// -----------------------------------------------------------------------------
// CSipConnection::StartMonitoringL
// -----------------------------------------------------------------------------
//
void CSipConnection::StartMonitoringL( TInt aError )
{
#ifdef CPPUNIT_TEST
aError; // silence warning
#else
// In unit testing hard coded IAPs cannot be expected
// to be valid in all environments.
// Not trying to load monitor plug-in by IAP in unit tests
iNetworkManager.RegisterObserverL( *iStateModel, iIapId, aError );
#endif
}
// -----------------------------------------------------------------------------
// CSipConnection::StopMonitoring
// -----------------------------------------------------------------------------
//
void CSipConnection::StopMonitoring()
{
iNetworkManager.Deregister( *iStateModel );
}
// -----------------------------------------------------------------------------
// CSipConnection::ContinueMonitoring
// -----------------------------------------------------------------------------
//
TBool CSipConnection::ContinueMonitoring( TInt aError )
{
return iNetworkManager.ContinueMonitoring( *iStateModel, aError );
}
// -----------------------------------------------------------------------------
// CSipConnection::MonitorConnectionClosure
// -----------------------------------------------------------------------------
//
TInt CSipConnection::MonitorConnectionClosure()
{
return iConnection->MonitorConnectionClosure( iServer );
}
// -----------------------------------------------------------------------------
// CSipConnection::StateModelChanged
// -----------------------------------------------------------------------------
//
void CSipConnection::StateModelChanged( CStateModel::TState aState )
{
CSIPConnection::TState oldState = iState;
SetState( aState );
if( oldState != iState )
{
TRAP_IGNORE(
iTUNetStatusObserver.ConnectionStateChangedL( iIapId, iState ) )
}
}
// -----------------------------------------------------------------------------
// CSipConnection::Destroy
// -----------------------------------------------------------------------------
//
void CSipConnection::Destroy()
{
iOwner.Destroy( iIapId );
}
// -----------------------------------------------------------------------------
// CSipConnection::DetermineConnectionTypeL
// -----------------------------------------------------------------------------
//
TInt CSipConnection::DetermineConnectionTypeL()
{
TInt bearer = KErrNotFound;
CMDBSession* cdb = CMDBSession::NewLC( KCDVersion1_1 );
cdb->SetAttributeMask( ECDHidden );
// Create an iap record
CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(
CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
CleanupStack::PushL( iapRecord );
iapRecord->SetRecordId( IapId() );
iapRecord->LoadL( *cdb );
TPtrC bearerType(iapRecord->iBearerType);
if(bearerType.CompareF(TPtrC(KCDTypeNameLANBearer)) == 0)
bearer = MSIPConnectionContext::ELanBearer;
else if(bearerType.CompareF(TPtrC(KCDTypeNameModemBearer)) == 0)
bearer = MSIPConnectionContext::EModemBearer;
CleanupStack::PopAndDestroy( iapRecord );
CleanupStack::PopAndDestroy( cdb );
return bearer;
}
// -----------------------------------------------------------------------------
// CSipConnection::State
// -----------------------------------------------------------------------------
//
CSIPConnection::TState CSipConnection::State()
{
return iState;
}
// -----------------------------------------------------------------------------
// CSipConnection::SystemStarted
// -----------------------------------------------------------------------------
//
void CSipConnection::SystemStarted()
{
iStateModel->EnterState( MStateModel::EInit, KErrNone );
}
// -----------------------------------------------------------------------------
// CSipConnection::CellularUsageAllowed
// -----------------------------------------------------------------------------
//
void CSipConnection::CellularUsageAllowed()
{
if(iWaitingForDataUsage)
{
iWaitingForDataUsage=EFalse;
__SIP_LOG( "CSipConnection::CellularUsageAllowed Execution" )
iStateModel->EnterState( MStateModel::EInit, KErrNone );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::TopViaHeader
// -----------------------------------------------------------------------------
//
CSIPViaHeader* CSipConnection::TopViaHeader( CSIPMessage* aMessage )
{
CSIPViaHeader* via = NULL;
if( aMessage->HasHeader( SIPStrings::StringF(SipStrConsts::EViaHeader) ) )
{
TSglQueIter< CSIPHeaderBase > iter =
aMessage->Headers( SIPStrings::StringF(SipStrConsts::EViaHeader) );
CSIPHeaderBase* header = iter;
via = static_cast< CSIPViaHeader* >( header );
}
return via;
}
// -----------------------------------------------------------------------------
// CSipConnection::SetState
// -----------------------------------------------------------------------------
//
void CSipConnection::SetState ( MStateModel::TState aState )
{
switch( aState )
{
case MStateModel::EInit:
{
iState = CSIPConnection::EInit;
break;
}
case MStateModel::EInactiveMonitoring:
case MStateModel::EInactiveConnecting:
{
iState = CSIPConnection::EInactive;
break;
}
case MStateModel::EActiveResolving:
{
// Does not yet change the current SIP connection state.
// The SIP connection state changes with the next state transition.
break;
}
case MStateModel::EActiveResolved:
{
iState = CSIPConnection::EActive;
break;
}
case MStateModel::ESuspended:
{
iState = CSIPConnection::ESuspended;
break;
}
case MStateModel::EUnavailable:
default:
{
iState = CSIPConnection::EUnavailable;
break;
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::Connection
// -----------------------------------------------------------------------------
//
RConnection& CSipConnection::Connection()
{
return iConnection->Connection();
}
// -----------------------------------------------------------------------------
// CSipConnection::NotifyIcmpErrorL
// -----------------------------------------------------------------------------
//
void CSipConnection::NotifyIcmpErrorL( const TInetAddr& aAddress )
{
CSipConnectionMgr::TICMPError error = CSipConnectionMgr::ENetUnreachable;
iFinder.IcmpErrorL( aAddress, error );
CTransportBase* listItem;
iListIter.SetToFirst();
while ( ( listItem = iListIter++ ) != 0 )
{
listItem->ICMPErrorL( error, aAddress );
}
}
// -----------------------------------------------------------------------------
// CSipConnection::IsConnectionActive
// -----------------------------------------------------------------------------
//
TBool CSipConnection::IsConnectionActive() const
{
return ( iState == CSIPConnection::EActive );
}
// -----------------------------------------------------------------------------
// CSipConnection::UpdateURIL
// -----------------------------------------------------------------------------
//
void CSipConnection::UpdateURIL(
CURIContainer& aURI,
const TInetAddr& aAddress,
TUint aProtocol ) const
{
__ASSERT_ALWAYS( aURI.IsSIPURI(), User::Leave( KErrSIPInvalidURIType ) );
CSIPURI& uri = *aURI.SIPURI();
RStringF transport;
if ( aProtocol == KProtocolInetTcp )
{
transport = SIPStrings::StringF( SipStrConsts::ETCP );
}
else if ( aProtocol == KProtocolTls )
{
transport = SIPStrings::StringF( SipStrConsts::ETLS );
}
else
{
User::Leave( KErrArgument );
}
uri.SetParamL( SIPStrings::StringF( SipStrConsts::ETransport ), transport );
uri.HostPort().SetPort( aAddress.Port() );
HBufC8* addressText = CTransport::ConvertInetAddrToTextL( aAddress );
CleanupStack::PushL( addressText );
uri.HostPort().SetHostL( *addressText );
CleanupStack::PopAndDestroy( addressText );
}
// -----------------------------------------------------------------------------
// CSipConnection::CSipConnection
// -----------------------------------------------------------------------------
//
CSipConnection::CSipConnection( MTransactionFinder& aFinder,
MServerTaFactory& aTaFactory,
MTimerManager& aTimer,
TUint aTOne,
const TSIPTransportParams& aParams,
RSocketServ& aServer,
MSigCompController& aSigCompHandler,
MConnectionStateObserver& aTUNetStatusObserver,
CNetworkManager& aNetworkManager,
MSipConnectionOwner& aOwner,
CNetworkInfo& aNetworkInfo,
CSIPNATTraversalController& aNATTraversal )
: iFinder( aFinder ),
iTaFactory( aTaFactory ),
iTUNetStatusObserver( aTUNetStatusObserver ),
iSigCompHandler( aSigCompHandler ),
iServer( aServer ),
iList( CTransportBase::iOffset ),
iListIter( iList ),
iTcpSenderList( CTcpResponseSender::iSenderOffset ),
iTcpSenderListIter( iTcpSenderList ),
iTOne( aTOne ),
iNetworkManager( aNetworkManager ),
iTimer( aTimer ),
iOwner( aOwner ),
iIapId( aParams.IapId() ),
iState( CSIPConnection::EInit ),
iNetworkInfo( aNetworkInfo ),
iNATTraversal( aNATTraversal )
{
}
// -----------------------------------------------------------------------------
// CSipConnection::~CSipConnection
// -----------------------------------------------------------------------------
//
CSipConnection::~CSipConnection()
{
delete iSettingsList;
iNetworkManager.Deregister( *iStateModel );
delete iStateModel;
// Use scope operator for keeping PC-Lint happy
CSipConnection::ReleaseTransportResources( ETrue );
delete iConnection;
}
// -----------------------------------------------------------------------------
// CSipConnection::ConstructL
// -----------------------------------------------------------------------------
//
void CSipConnection::ConstructL()
{
iWaitingForDataUsage = EFalse;
iSettingsList = COwnerSettingsList::NewL();
iStateModel = CStateModel::NewL( *this, iTimer );
iConnection = CConnectionContainer::NewL( *iStateModel );
if ( iOwner.IsSystemStarted())
{
if ((ConnectionType() == MSIPConnectionContext::EModemBearer) && (!iOwner.IsCellularDataUsageAllowed()) )
{
iWaitingForDataUsage = ETrue;
__SIP_LOG( "CSipConnection::ConstructL() is blocking Connection Start Up..." )
return;
}
else
{
__SIP_LOG( "CSipConnection::ConstructL() is Allowing Connection Start Up..." )
iStateModel->EnterState( MStateModel::EInit, KErrNone );
}
}
}
// -----------------------------------------------------------------------------
// CSipConnection::ConnectionError
// -----------------------------------------------------------------------------
//
TInt CSipConnection::ConnectionError()
{
return iStateModel->Error();
}
// -----------------------------------------------------------------------------
// CSipConnection::ConnectionType()
// -----------------------------------------------------------------------------
//
TInt CSipConnection::ConnectionType()
{
TInt type = MSIPConnectionContext::EModemBearer;
TRAP_IGNORE( type = DetermineConnectionTypeL( ) )
return type;
}