--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/ConnectionMgr/src/CSipConnection.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,2080 @@
+// 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;
+ }
+