diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/ConnectionMgr/src/CSipConnection.cpp --- /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 +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 iter = aMessage.Headers( route ); + iter.SetToFirst(); + CSIPHeaderBase* header = iter; + if ( header ) + { + CSIPRouteHeader* routeHeader = static_cast( 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(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(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( 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& aResult, + MSIPServerResolverObserver* aObserver ) + { + __ASSERT_ALWAYS( iServerResolver, User::Leave( KErrNotReady ) ); + + // Have to do const cast in order to get binding observer + MSIPNATBindingObserver* bindingObserver = + const_cast( 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( + 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; + } +