internetradio2.0/streamsourcesrc/irsocketopener.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 19 Apr 2010 14:01:53 +0300
changeset 0 09774dfdd46b
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2006-2007 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:  Socket opener implementation
*
*/


#include <e32property.h>
#include <HttpDownloadMgrCommon.h>
#include <in_sock.h>
#include <uriutils.h>

#include "irpubsubkeys.h"
#include "irdebug.h"
#include "irnetworkcontroller.h"
#include "irsocketopener.h"
#include "irstationconnection.h"
#include "irstreamsourceerrors.h"
#include "irstreamsourceliterals.h"

const TInt KIRSOTimeOutValue = 10000000;

// ---------------------------------------------------------------------------
// CIRSocketOpener::NewL
// ---------------------------------------------------------------------------
//
CIRSocketOpener* CIRSocketOpener::NewL( RSocket& aSocket, CIRStationConnection& aOwner )
	{
	CIRSocketOpener* self = new ( ELeave ) CIRSocketOpener( aSocket, aOwner );
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	return self;
	}
	
// ---------------------------------------------------------------------------
// CIRSocketOpener::CIRSocketOpener
// ---------------------------------------------------------------------------
//
CIRSocketOpener::CIRSocketOpener( RSocket& aSocket, CIRStationConnection& aOwner )
	:CActive( EPriorityStandard ), iPort( KDefaultPort ), iSocket( aSocket), iOwner( aOwner )
	{
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::ConstructL
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::ConstructL()
	{
	IRLOG_DEBUG( "CIRSocketOpener::ConstructL" );	
	CActiveScheduler::Add( this );
	iState = EIRIdle;
	iSocketTimer = CIRSocketTimeOutTimer::NewL( CActive::EPriorityHigh,*this );

	CIRNetworkController* networkControllerHandle = CIRNetworkController::OpenL();
	CleanupClosePushL( *networkControllerHandle );

    TProtocolName protocolName( KTcpProtocol );
	TProtocolDesc protocolInfo;
	
	networkControllerHandle->GetIRSocketServer().FindProtocol( protocolName, protocolInfo );
	
	iResolver.Close();

	User::LeaveIfError( iResolver.Open( networkControllerHandle->GetIRSocketServer(),
	                                   protocolInfo.iAddrFamily, protocolInfo.iProtocol,
	                                   networkControllerHandle->GetIRConnection() ) );

	IRLOG_DEBUG( "CIRSocketOpener::ConstructL - Opened resolver." );
	User::LeaveIfError( iSocket.Open( networkControllerHandle->GetIRSocketServer(),
				 protocolInfo.iAddrFamily,protocolInfo.iSockType,protocolInfo.iProtocol,
	                                  networkControllerHandle->GetIRConnection() ) );
    IRLOG_DEBUG( "CIRSocketOpener::ConstructL - Opened socket." );
	                                   
    CleanupStack::PopAndDestroy();
	IRLOG_DEBUG( "CIRSocketOpener::ConstructL - Exiting." );	    
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::CIRSocketOpener
// ---------------------------------------------------------------------------
//
CIRSocketOpener::~CIRSocketOpener()
	{
	Cancel();
//	iResolver.Close()	
    iHost.Close();	
	delete iSocketTimer;	
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::ResolveAddress()
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::ResolveAddress()
	{
	IRLOG_INFO2( "CIRSocketOpener::ResolveAddress - %S", &iHost );
    Cancel();
	iState = EIRResolving;

	iSocketTimer->Cancel();
	iSocketTimer->After( KIRSOTimeOutValue );
	
	iResolver.GetByName( iHost, iResolvedHostInfo, iStatus );
	SetActive();

	IRLOG_DEBUG( "CIRSocketOpener::ResolveAddress - Exiting." );                
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::ConnectToAddress()
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::ConnectToAddress()
	{
	IRLOG_INFO( "CIRSocketOpener::ConnectToAddress" );
    Cancel();
	iState = EIRConnecting;

	iSocketTimer->Cancel();
	iSocketTimer->After( KIRSOTimeOutValue );
	
	iSocket.Connect( iSockAddr, iStatus );
	SetActive();

	IRLOG_DEBUG( "CIRSocketOpener::ConnectToAddress - Exiting." );    
    }   

// ---------------------------------------------------------------------------
// CIRSocketOpener::ExtractUriComponents
// ---------------------------------------------------------------------------
//
TBool CIRSocketOpener::ExtractUriComponentsL(const TDesC& aUrl)
	{
	IRLOG_DEBUG( "CIRSocketOpener::ExtractUriComponentsL" );    

    TBool retMe = EFalse;

	if( !UriUtils::HasInvalidChars( aUrl ) )
		{
    	// Initialize the Uri Parser
    	CUri8* uri = UriUtils::CreateUriL( aUrl );
    	CleanupStack::PushL( uri );
    	
    	const TUriC8& accessorUri = uri->Uri(); 

        iHost.Close();
    
        const TDesC8& host = accessorUri.Extract( EUriHost ); 
        if ( host.Length() > 0 )
            {
            if ( iHost.Create( host.Length() ) == KErrNone )
                {
                iHost.Copy( host );
            
	            TLex8 uriLex( accessorUri.Extract( EUriPort ) );
	            if ( uriLex.Val( iPort ) != KErrNone )
	                {
    	            iPort = KDefaultPort;
	                }
                retMe = ETrue;	            
                }
            }
        CleanupStack::PopAndDestroy( uri );
		}
	IRLOG_DEBUG2( "CIRSocketOpener::ExtractUriComponentsL - Returning %d.", retMe );        
	return retMe;
	}


// ---------------------------------------------------------------------------
// CIRSocketOpener::RunL
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::RunL()
	{
	IRLOG_INFO3( "CIRSocketOpener::RunL - iStatus = %d, iState = %d", iStatus.Int(), iState );

	if( iStatus == KErrNone )
		{
		switch( iState )
			{
			case EIRResolving:
				iSocketTimer->Cancel();
				iSockAddr = ( iResolvedHostInfo() ).iAddr;
				iSockAddr.SetPort( iPort );
				ConnectToAddress();
				break;
			case EIRConnecting:
    			iSocketTimer->Cancel();
				iState = EIRReady;
				iOwner.ConnectionReady();
				break;
			default:
                __ASSERT_DEBUG( EFalse, User::Invariant() );
    			break;
			}
		}
	else 
		{
		switch( iState )
			{
			case EIRResolving:
				IRLOG_ERROR( "CIRConnectionHandler::RunL - EIRResolving" );
				iSocketTimer->Cancel();
				iOwner.ConnectionError( KIRStreamSourceLookupError );
				break;
			case EIRConnecting: 
				IRLOG_ERROR( "CIRConnectionHandler::RunL - EConnecting"); 
				iSocketTimer->Cancel();
				iOwner.ConnectionError( KIRStreamSourceConnectionError );
				break;
			default:
				IRLOG_FATAL2( "CIRConnectionHandler::RunL - Error in unexpected state (%d)", iStatus.Int() );
                __ASSERT_DEBUG( EFalse, User::Invariant() );				
				break;
			}
		}
	IRLOG_DEBUG( "CIRSocketOpener::RunL - Exiting." );
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::Connect
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::ConnectL( const TDesC& aUrl )
	{
    IRLOG_INFO2( "CIRSocketOpener::ConnectL - %S", &aUrl );
	if( ExtractUriComponentsL( aUrl ) )
		{
		ResolveAddress();		  	
		}
	else
		{
		IRLOG_ERROR( "CIRConnectionHandler::ConnectL - Invalid URL" );
		iOwner.ConnectionError( KIRStreamSourceInvalidUrl );		  		
		}  
	IRLOG_DEBUG( "CIRSocketOpener::ConnectL - Exiting." );		
	}

// ---------------------------------------------------------------------------
// CIRSocketOpener::TimerExpired
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::TimerExpired()
	{
	switch( iState )
		{
		case EIRResolving: 
			Cancel();
			IRLOG_ERROR( "CIRSocketOpener::TimerExpired - Timed out while looking up server." );
			iOwner.ConnectionError( KIRStreamSourceTimeOut );
			break;
		
		case EIRConnecting: 
		    Cancel();
			IRLOG_ERROR( "CIRSocketOpener::TimerExpired - Connecting to server timed out." );   	 		    
			iOwner.ConnectionError( KIRStreamSourceTimeOut );
			break;
		default:
            __ASSERT_DEBUG( EFalse, User::Invariant() );				
			break;
		} 
	}


// ---------------------------------------------------------------------------
// CIRSocketOpener::DoCancel
// ---------------------------------------------------------------------------
//
void CIRSocketOpener::DoCancel()
	{
	IRLOG_DEBUG( "CIRSocketOpener::DoCancel." );	
	iResolver.Cancel();
	iSocket.CancelAll();
	
	iSocketTimer->Cancel();
	IRLOG_DEBUG( "CIRSocketOpener::DoCancel - Exiting." );		
	}