upnp/upnpstack/dlnawebserver/src/upnpsocketshutdown.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:12:20 +0200
changeset 0 f5a58ecadc66
permissions -rw-r--r--
Revision: 201003

/** @file
* Copyright (c) 2005-2006 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 "upnptcpsession.h"
#include "upnptcpsessionreader.h"
#include "upnptcpsessionwriter.h"
#include "upnphttpfiletransferwriter.h"
#include "upnphttpfiletransferreader.h"
#include "upnpsocketshutdown.h"
#include "upnpnotifytimer.h"



// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::NewL
//
// -----------------------------------------------------------------------------
//
CUpnpSocketShutdown* CUpnpSocketShutdown::NewL( CUpnpTcpSession& aSession, RSocket& aSocket, TThreadPriority aPriority )
    {
    CUpnpSocketShutdown* self = new ( ELeave ) CUpnpSocketShutdown( aSession, aSocket, aPriority );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::CUpnpSocketShutdown
//
// -----------------------------------------------------------------------------
//
CUpnpSocketShutdown::CUpnpSocketShutdown( CUpnpTcpSession& aSession, RSocket& aSocket, TThreadPriority aPriority ):CActive( aPriority ),iSession( aSession ),iSocket( aSocket ),iInternalState(EUnknown), iSessionTimeouted( EFalse )
    {
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::ConstructL
//
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::ConstructL()
    {
    CActiveScheduler::Add( this );
    iInputTimeoutTimer = CUpnpNotifyTimer::NewL( this );
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::~CUpnpSocketShutdown
//
// -----------------------------------------------------------------------------
//
CUpnpSocketShutdown::~CUpnpSocketShutdown()
    {
    Cancel();
    delete iInputTimeoutTimer;
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::ShutdownImmediate
// Disconnect connection
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::ShutdownImmediate()
    {
    iSession.iTcpReader->Cancel();       
    iSession.iTcpWriter->Cancel();      
    if( iSession.iFTReader )
        {
        iSession.iFTReader->Cancel();
        }
    if( iSession.iFTWriter )
        {
        iSession.iFTWriter->Cancel();
        }
    iSocket.Shutdown( iSocket.EImmediate, iStatus );
    iInternalState = ENotConnected;                
    SetActive();    
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::ShutdownStop
// Disconnect connection
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::ShutdownStop()
    {
    if ( iInternalState == EUnknown )
        {
        iSession.iTcpReader->CancelTimers();
        if( iSession.iFTReader )
            {
            iSession.iFTReader->CancelTimers();
            }
        
        if( iSession.iTcpReader->IsActive() 
            || ( iSession.iFTReader && iSession.iFTReader->IsActive() ) 
          )
            {
            iSocket.Shutdown( iSocket.EStopOutput, iStatus );            
            iInternalState = EShuttingDownStopOutput ;               
            }
        else
            {
            iSocket.Shutdown( iSocket.ENormal, iStatus );
            iInternalState = EShuttingDownNormal;
            }
        SetActive();
        }
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::MarksTimeout
// Marks if timeout occured on session
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::MarksTimeout()
    {
    iSessionTimeouted = ETrue;
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::HandleError
// Disconnect connection
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::HandleError( TInt /*aError*/ )
    {
    switch ( iInternalState )
        {
        case EUnknown: // error happened during reading/writing - start shutdown procedure
            ShutdownStop();
            break;
        case EShuttingDownStopOutput: // input error appeares while shutdown stop output is pending
                                      // when it returns shutdown immediate is invoked in RunL  
            iInternalState = EInputErrorReceived;
            break;
        case EWaitingForInputError: // error response from reader after shutdown stop output                  
            ShutdownImmediate();
            break;
        case EShuttingDownNormal: // do nothimg session is being closed
        case ENotConnected: // do nothing session is closed
        default:
            break;        
        }
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::HandleError
// Disconnect connection
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::RunL()
    {
    switch( iInternalState )
        {
        case EShuttingDownNormal: // shutdown normal response came
            ShutdownImmediate();
            break;
        case EShuttingDownStopOutput: // shutdown stop output response came
                                // waiting for KErrEof from HandleError()                                
            if( !iSessionTimeouted )
                {
                iInternalState = EWaitingForInputError;                                
                iInputTimeoutTimer->Cancel();
                iInputTimeoutTimer->After(KSessionTimeout, EFalse);     
                break;                
                }
        case EInputErrorReceived: // input error came before stop output finished
            ShutdownImmediate();
            break;
        case ENotConnected:  // shutdown immediate response came          
            iSession.CloseSocketL();           
            break;
        default:
            break;    
        }
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::TimerEventL
// Disconnect connection
// -----------------------------------------------------------------------------
//        
void CUpnpSocketShutdown::TimerEventL( CUpnpNotifyTimer* /*aTimer*/ )
    {
     switch( iInternalState )
        {
        case EWaitingForInputError: // waiting for input error timeout 
            ShutdownImmediate();
            break;            
        default: 
            break;
        }
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::DoCancel
// Disconnect connection
// -----------------------------------------------------------------------------
//
void CUpnpSocketShutdown::DoCancel()
    {
    }

// -----------------------------------------------------------------------------
// CUpnpSocketShutdown::HandleError
// Disconnect connection
// -----------------------------------------------------------------------------
//
TInt CUpnpSocketShutdown::RunError( TInt /*aError*/ )
    {
    return KErrNone;
    }