/*
* Copyright (c) 2005 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:
*
*/
#include <badesca.h>
#include <in_pkt.h>
#include <sip.h>
#include <sipprofile.h>
#include <sipdialog.h>
#include <sipinvitedialogassoc.h>
#include <sipcontactheader.h>
#include <sipprofileregistry.h>
#include "mcesip.h"
#include "mcesrvlogs.h"
#include "mcesipconnection.h"
#include "mcesipmanager.h"
#include "mcesipsession.h"
#include "mcecssessionimplementation.h"
#include "mcelocaladdrresolver.h"
//const TInt KMaxAddressLength = 256;
// -----------------------------------------------------------------------------
// CMceSipConnection::NewLC
// -----------------------------------------------------------------------------
//
CMceSipConnection* CMceSipConnection::NewLC(
CMceSipManager& aSessionManager,
CSIPProfile& aProfile,
CSIPProfileRegistry& aProfileRegistry )
{
CMceSipConnection* self = new (ELeave) CMceSipConnection( aSessionManager,
aProfile );
CleanupStack::PushL( self );
self->ConstructL( aProfile, aProfileRegistry );
return self;
}
// -----------------------------------------------------------------------------
// CMceSipConnection::NewLC
// -----------------------------------------------------------------------------
//
CMceSipConnection* CMceSipConnection::NewLC( CMceSipManager& aSessionManager,
TUint32 aIAPId )
{
CMceSipConnection* self = new (ELeave) CMceSipConnection( aSessionManager,
aIAPId );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
#define MCE_SIP_CONNECTION_UNUSABLE( connection )\
(connection->State() == CSIPConnection::EInactive ||\
connection->State() == CSIPConnection::EUnavailable )
// -----------------------------------------------------------------------------
// CMceSipConnection::~CMceSipConnection
// -----------------------------------------------------------------------------
//
CMceSipConnection::~CMceSipConnection()
{
MCESRV_DEBUG("CMceSipConnection::CMceSipConnection, Entry")
delete iClientConnection;
iSessions.Reset();
iSessions.Close();
delete iLocalAddrResolver;
MCESRV_DEBUG("CMceSipConnection::CMceSipConnection, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::Connection
// -----------------------------------------------------------------------------
//
CSIPConnection& CMceSipConnection::Connection() const
{
return *iClientConnection;
}
// -----------------------------------------------------------------------------
// CMceSipConnection::State
// -----------------------------------------------------------------------------
//
CSIPConnection::TState CMceSipConnection::State() const
{
return iClientConnection->State();
}
// -----------------------------------------------------------------------------
// CMceSipConnection::AccessPointId
// -----------------------------------------------------------------------------
//
TUint32 CMceSipConnection::AccessPointId() const
{
return iIAPId;
}
// -----------------------------------------------------------------------------
// CMceSipConnection::AttachL
// -----------------------------------------------------------------------------
//
void CMceSipConnection::AttachL( CMceCsSubSession& aSession )
{
User::LeaveIfError( MCE_SIP_CONNECTION_UNUSABLE( iClientConnection ) ?
KErrNotReady : KErrNone );
User::LeaveIfError(
iSessions.Find( &aSession ) < 0 ? KErrNone : KErrArgument );
iSessions.AppendL( &aSession );
}
// -----------------------------------------------------------------------------
// CMceSipConnection::Detach
// -----------------------------------------------------------------------------
//
TInt CMceSipConnection::Detach( CMceCsSubSession& aSession )
{
TInt index = iSessions.Find( &aSession );
if ( index >= KErrNone )
{
iSessions.Remove( index );
}
return iSessions.Count();
}
// -----------------------------------------------------------------------------
// CMceSipConnection::CMceSipConnection
// -----------------------------------------------------------------------------
//
CMceSipConnection::CMceSipConnection ( CMceSipManager& aSessionManager,
CSIPProfile& aProfile )
: iIAPId( (TUint32)KErrNotFound ),
iSessionManager( aSessionManager )
{
aProfile.GetParameter( KSIPAccessPointId, iIAPId );
}
// -----------------------------------------------------------------------------
// CMceSipConnection::CMceSipConnection
// -----------------------------------------------------------------------------
//
CMceSipConnection::CMceSipConnection ( CMceSipManager& aSessionManager,
TUint32 aIAPId )
: iIAPId( aIAPId ),
iSessionManager( aSessionManager )
{
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ConstructL
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ConstructL( CSIPProfile& aProfile,
CSIPProfileRegistry& aProfileRegistry )
{
MCESRV_DEBUG("CMceSipConnection::ConstructL, Entry")
if ( !aProfileRegistry.IsEnabled( aProfile ) )
{
MCESRV_DEBUG("CMceSipConnection::ConstructL, enabling profile")
aProfileRegistry.EnableL( aProfile, *this );
}
iClientConnection = aProfileRegistry.ConnectionL( aProfile );
iLocalAddrResolver =
CMceLocalAddrResolver::NewL(
iSessionManager.SocketServ(),
AccessPointId() );
MCESRV_DEBUG("CMceSipConnection::ConstructL, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ConstructL
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ConstructL( )
{
MCESRV_DEBUG("CMceSipConnection::ConstructL, Entry")
MCESRV_DEBUG("CMceSipConnection::ConstructL, new connection")
iClientConnection =
CSIPConnection::NewL( iSessionManager.SIPClient(),
AccessPointId(),
*this );
iLocalAddrResolver =
CMceLocalAddrResolver::NewL(
iSessionManager.SocketServ(),
AccessPointId() );
MCESRV_DEBUG("CMceSipConnection::ConstructL, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingRequest
// -----------------------------------------------------------------------------
//
void CMceSipConnection::IncomingRequest(
CSIPServerTransaction* aTransaction )
{
MCESRV_DEBUG("CMceSipConnection::IncomingRequest( sa ), Entry")
MCESRV_DEBUG_SVALUE("request", MceSip::Method( *aTransaction ).DesC() )
TInt error = KErrNone;
TBool sessionConsumed = EFalse;
TBool requestConsumed = EFalse;
sessionConsumed = iSessionManager.Consumes( *aTransaction );
if ( sessionConsumed )
{
TRAP( error, iSessionManager.CreateSubSessionL( aTransaction, *this ) );
requestConsumed = error ? EFalse : ETrue;
}
else
{
CMceCsSubSession* session = NULL;
TInt index = 0;
while ( !requestConsumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
sessionConsumed = session->Consumes( *aTransaction );
if ( sessionConsumed )
{
requestConsumed = session->MessageRequestReceived( aTransaction );
}
}
}
if ( !sessionConsumed )
{
MCESRV_DEBUG("IncomingRequest( sa ): not consumed ->discard")
MceSip::DiscardRequest( aTransaction, KMceSipNotImplemented );
}
else if ( !requestConsumed || error )
{
MCESRV_DEBUG("IncomingRequest( sa ): error->discard")
MceSip::DiscardRequest( aTransaction );
}
else
{
// NOP
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::IncomingRequest( sa ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingRequest
// -----------------------------------------------------------------------------
//
void CMceSipConnection::IncomingRequest (
CSIPServerTransaction* aTransaction,
CSIPDialog& aDialog )
{
MCESRV_DEBUG("CMceSipConnection::IncomingRequest( inside dialog ), Entry")
MCESRV_DEBUG_SVALUE("request", MceSip::Method( *aTransaction ).DesC() )
CMceCsSubSession* session = NULL;
CMceCsSubSession* assocSession = NULL;
TBool sessionConsumed = EFalse;
TBool requestConsumed = EFalse;
TInt index = 0;
while ( !requestConsumed && index < iSessions.Count() )
{
TBool assocDialog( EFalse );
session = iSessions[ index++ ];
sessionConsumed = session->Consumes( aDialog, *aTransaction, assocDialog );
if ( sessionConsumed )
{
requestConsumed = session->DialogRequestReceived( aTransaction, aDialog );
}
if ( assocDialog && !assocSession )
{
assocSession = session;
}
}
TInt error = KErrNone;
if( !requestConsumed )
{
index = 0;
while ( !requestConsumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
if ( !session->Client().IsOrphan() &&
session->Dialog()->Dialog() == aDialog )
{
TRAP( error, iSessionManager.CreateSubSessionL(
aTransaction,
session->Client().ClientSession(),
*this,
assocSession ) );
sessionConsumed = error ? EFalse : ETrue;
requestConsumed = sessionConsumed;
}
}
}
if ( !sessionConsumed )
{
// Unknown method
MCESRV_DEBUG("IncomingRequest: not consumed -> discard")
MceSip::DiscardRequest( aTransaction, KMceSipNotImplemented );
}
else if ( !requestConsumed || error )
{
MCESRV_DEBUG("IncomingRequest: error -> discard")
MceSip::DiscardRequest( aTransaction );
}
else
{
// NOP
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::IncomingRequest( inside dialog ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingResponse
// -----------------------------------------------------------------------------
//
void CMceSipConnection::IncomingResponse(
CSIPClientTransaction& aTransaction )
{
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( standalone ), Entry")
MCESRV_DEBUG_DVALUE("response", MceSip::ResponseCode( aTransaction ) )
MCESRV_DEBUG_SVALUE("to", aTransaction.Type().DesC() )
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
consumed = session->Consumes( aTransaction );
if ( consumed )
{
session->MessageResponseReceived( aTransaction );
}
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( standalone ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingResponse
// -----------------------------------------------------------------------------
//
void CMceSipConnection::IncomingResponse(
CSIPClientTransaction& aTransaction,
CSIPDialogAssocBase& aDialogAssoc )
{
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( inside dialog ), Entry")
MCESRV_DEBUG_DVALUE("response", MceSip::ResponseCode( aTransaction ) )
MCESRV_DEBUG_SVALUE("to", aTransaction.Type().DesC() )
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
if ( session->Consumes( aTransaction ) )
{
consumed = ETrue;
session->ResponseReceivedWithinDialog( aTransaction, aDialogAssoc );
}
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( inside dialog ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingResponse
// -----------------------------------------------------------------------------
//
void CMceSipConnection::IncomingResponse (
CSIPClientTransaction& aTransaction,
CSIPInviteDialogAssoc* aDialogAssoc )
{
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( forked ), Entry")
MCESRV_DEBUG_DVALUE("response", MceSip::ResponseCode( aTransaction ) )
MCESRV_DEBUG_SVALUE("to", aTransaction.Type().DesC() )
// Find the session
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
TInt error = KErrNone;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
if ( session->Consumes( aTransaction ) &&
session->Type() == CMceCsSubSession::EOutSIPSession )
{
consumed = ETrue;
TRAP( error, static_cast<CMceSipSession*>( session )->
InviteForkedL( aTransaction, aDialogAssoc ) );
}
}
if ( error != KErrNone || !consumed )
{
Reject( aDialogAssoc );
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( forked ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IncomingResponse
// -----------------------------------------------------------------------------
//
void
CMceSipConnection::IncomingResponse(
CSIPClientTransaction& /*aTransaction*/,
CSIPRegistrationBinding& /*aRegistration*/ )
{
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( reg ), Entry")
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( reg ), NOT IMPLEMENTED")
//NOT IMPLEMENTED
MCESRV_DEBUG("CMceSipConnection::IncomingResponse( reg ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured(
TInt aError,
CSIPTransactionBase& aTransaction )
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( standalone ), Entry")
MCESRV_DEBUG_DVALUE("error", aError )
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
consumed = session->Consumes( aTransaction );
if ( consumed )
{
session->ErrorOccured( aError, aTransaction );
}
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( standalone ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured (
TInt aError,
CSIPTransactionBase& aTransaction,
CSIPDialogAssocBase& aDialogAssoc)
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( inside dialog ), Entry")
MCESRV_DEBUG_DVALUE("error", aError )
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
if ( session->Dialog() == &aDialogAssoc &&
session->Consumes( aTransaction ) )
{
consumed = ETrue;
session->ErrorOccured( aError, aTransaction );
}
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::ErrorOccured(inside dialog ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured(
TInt aError,
CSIPDialogAssocBase& aDialogAssoc )
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( dialog ), Entry")
MCESRV_DEBUG_DVALUE("error", aError )
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
if ( session->Dialog() == &aDialogAssoc )
{
session->ErrorOccured( aError );
consumed = ETrue;
}
}
iSessionManager.Cleanup();
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( dialog ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::InviteCompleted
// -----------------------------------------------------------------------------
//
void CMceSipConnection::InviteCompleted(
CSIPClientTransaction& aTransaction )
{
MCESRV_DEBUG("CMceSipConnection::InviteCompleted, Entry")
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
consumed = session->Consumes( aTransaction );
if ( consumed )
{
session->InviteCompleted( aTransaction );
}
}
MCESRV_DEBUG("CMceSipConnection::InviteCompleted, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::InviteCanceled
// -----------------------------------------------------------------------------
//
void CMceSipConnection::InviteCanceled(
CSIPServerTransaction& aTransaction )
{
MCESRV_DEBUG("CMceSipConnection::InviteCanceled, Entry")
CMceCsSubSession* session = NULL;
TBool consumed = EFalse;
TInt index = 0;
while ( !consumed && index < iSessions.Count() )
{
session = iSessions[ index++ ];
consumed = session->Consumes( aTransaction );
if ( consumed )
{
session->Canceled();
}
}
MCESRV_DEBUG("CMceSipConnection::InviteCanceled, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ConnectionStateChanged
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ConnectionStateChanged(
CSIPConnection::TState aState )
{
MCESRV_DEBUG("CMceSipConnection::ConnectionStateChanged, Entry")
MCESRV_DEBUG_DVALUE("state", aState )
TInt index = 0;
while ( index < iSessions.Count() )
{
CMceCsSubSession* session = iSessions[ index++ ];
session->ConnectionStateChanged( aState );
if ( MCE_SIP_CONNECTION_UNUSABLE( iClientConnection ) )
{
session->Canceled();
}
}
MCESRV_DEBUG("CMceSipConnection::ConnectionStateChanged, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured(
TInt /*aError*/,
CSIPClientTransaction& /*aTransaction*/,
CSIPRegistrationBinding& /*aRegistration*/)
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( reg ), Entry")
MCESRV_DEBUG("NOT IMPLEMENTED")
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( reg ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured(
TInt /*aError*/,
CSIPRefresh& /*aSIPRefresh*/ )
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( refresh ), Entry")
MCESRV_DEBUG("NOT IMPLEMENTED")
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( refresh ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::ErrorOccured
// -----------------------------------------------------------------------------
//
void CMceSipConnection::ErrorOccured(
TInt /*aError*/,
CSIPRegistrationBinding& /*aRegistration*/ )
{
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( sa reg ), Entry")
MCESRV_DEBUG("NOT IMPLEMENTED")
MCESRV_DEBUG("CMceSipConnection::ErrorOccured( sa reg ), Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::Reject
// -----------------------------------------------------------------------------
//
void CMceSipConnection::Reject( CSIPInviteDialogAssoc* aDialogAssoc )
{
MCESRV_DEBUG("CMceSipConnection::Reject( assoc ), Entry")
delete aDialogAssoc;
MCESRV_DEBUG("CMceSipConnection::Reject( assoc ), Entry")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::LocalIPAddressL
// -----------------------------------------------------------------------------
//
TInetAddr CMceSipConnection::LocalIPAddressL( TInetAddr* aNextHop )
{
MCESRV_DEBUG("CMceSipConnection::LocalIPAddressL, Entry")
TInetAddr localIpAddress;
iLocalAddrResolver->RefreshLocalAddressesL();
FillWithMatchingAddrFamily( localIpAddress, aNextHop );
MCESRV_DEBUG("CMceSipConnection::LocalIPAddressL, Exit")
return localIpAddress;
}
// -----------------------------------------------------------------------------
// CMceSipConnection::UpdateConnectionL
// -----------------------------------------------------------------------------
//
void CMceSipConnection::UpdateConnectionL( TUint aSignallingTypeOfService )
{
if ( aSignallingTypeOfService != iCurrentSignallingTypeOfService )
{
MCESRV_DEBUG_DVALUE( "CMceSipConnection::UpdateConnectionL, tos",
aSignallingTypeOfService )
iClientConnection->SetOptL( KSoIpTOS,
KProtocolInetIp,
aSignallingTypeOfService );
iCurrentSignallingTypeOfService = aSignallingTypeOfService;
MCESRV_DEBUG("CMceSipConnection::UpdateConnectionL, tos set")
}
}
// -----------------------------------------------------------------------------
// CMceSipConnection::FillWithMatchingAddrFamily
// -----------------------------------------------------------------------------
//
void CMceSipConnection::FillWithMatchingAddrFamily( TInetAddr& aAddr,
const TInetAddr* aNextHop )
{
MCESRV_DEBUG("CMceSipConnection::FillWithMatchingAddrFamily, Entry")
MCESRV_DEBUG_ADDRVALUE(
"CMceSipConnection::FillWithMatchingAddrFamily: local IP addr",
iLocalAddrResolver->Addr() )
MCESRV_DEBUG_ADDRVALUE(
"CMceSipConnection::FillWithMatchingAddrFamily: local IPv4 addr",
iLocalAddrResolver->IPv4Addr() )
if ( iLocalAddrResolver->HasIPv4Addr() )
{
aAddr = iLocalAddrResolver->IPv4Addr();
}
else
{
aAddr = iLocalAddrResolver->Addr();
}
if ( aNextHop )
{
MCESRV_DEBUG_ADDRVALUE(
"CMceSipConnection::FillWithMatchingAddrFamily: next hop",
*aNextHop )
MCESRV_DEBUG_DVALUE(
"CMceSipConnection::FillWithMatchingAddrFamily: next hop family",
aNextHop->Family() )
if ( aNextHop->Family() == KAfInet )
{
if ( !iLocalAddrResolver->HasIPv4Addr() &&
( aAddr.IsV4Compat() || aAddr.IsV4Mapped() ) )
{
aAddr.ConvertToV4();
}
}
else
{
aAddr = iLocalAddrResolver->Addr();
if ( aAddr.Family() == KAfInet )
{
aAddr.ConvertToV4Compat();
}
}
}
MCESRV_DEBUG_ADDRVALUE(
"CMceSipConnection::FillWithMatchingAddrFamily returns", aAddr )
MCESRV_DEBUG("CMceSipConnection::FillWithMatchingAddrFamily, Exit")
}
// -----------------------------------------------------------------------------
// CMceSipConnection::IsProfileUsedInSession
// -----------------------------------------------------------------------------
//
TBool CMceSipConnection::IsProfileUsedInSession( CSIPProfile& aProfile )
{
TBool result = EFalse;
for( TInt i = 0; i < iSessions.Count() && !result; i++ )
{
result = ( &aProfile == &iSessions[ i ]->Profile() );
}
return result;
}
//EOF