upnp/upnpstack/dlnawebserver/src/upnptcpsession.cpp
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/dlnawebserver/src/upnptcpsession.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,765 @@
+/** @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:  Declares ControlPoint class.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "upnptcpsessionreader.h"
+#include "upnphttpfiletransferreader.h"
+#include "upnphttpchunkfiletransferreader.h"
+#include "upnphttpfiletransferwriter.h"
+#include "upnptcpsessionwriter.h"
+#include "upnphttpsession.h"
+#include "upnphttpfileaccess.h"
+#include "upnphttpmessagefactory.h"
+#include "upnphttpbuffer.h"
+#define KLogFile _L("DLNAWebServer.txt")
+#include "upnpcustomlog.h"
+
+//CONSTANTS
+const TInt KMaxExportRetry = 0;
+ 
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::CUpnpTcpSession
+// C++ constructor used when remote host issued connection to server
+// -----------------------------------------------------------------------------
+//
+CUpnpTcpSession::CUpnpTcpSession( RSocket& aSocket,
+                                  TThreadPriority aPriority )
+    : iSocket( aSocket ),
+      iTimeoutCurrentValue( KSessionTimeout ), iTimeoutSessionValue(KSessionTimeout)
+    {
+    iInitialPriority = aPriority;
+
+    iSessionNeedsErrorReply = ETrue;
+    iDisconnectNotification=ETrue;
+    iContinuedMessageDownload = EFalse;
+    iExportRetryCounter = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::TcpConstructL
+// Two-phased constructor
+// constructor that can leave. Used from derived classes.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::TcpConstructL( RSocket aSocket,
+                                     TInt aReadBufferSize,
+                                     TInt aFileReadBufferSize )
+    { 
+    
+    LOGS1( "%i, CUpnpTcpSession::TcpConstructL(RSocket)", iId );
+
+    aSocket.RemoteName( iAddr );
+    iAddr.ConvertToV4();
+          
+    // Create timeout timer and start it.
+    iTimeoutTimer = CUpnpNotifyTimer::NewL( this );
+    iSocketShutdown = CUpnpSocketShutdown::NewL( *this, iSocket, iInitialPriority );
+
+    // Create socket read and write active objects
+    iTcpReader = CUpnpTcpSessionReader::NewL( *this, iSocket,
+                                     iInitialPriority, aReadBufferSize );    
+    iTcpWriter = CUpnpTcpSessionWriter::NewL( *this, iSocket, iInitialPriority );
+
+    iDisconnectNotification = ETrue;
+    iIsPersistent = ETrue;
+    iFileReadBufferSize = aFileReadBufferSize;
+
+    SetState( EConnected );
+
+    InitialReceiveL();
+    
+    StartTimeoutTimer( iSessionNeedsErrorReply );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::FileTransferReaderConstructL
+// Creates and activates the File Transfer reder object
+// constructor that can leave. Used from derived classes.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::FileTransferReaderConstructL()
+    {
+    LOGS1( "%i, CUpnpTcpSession::FileTransferConstructL", iId );
+        
+    // Create filetransfer reader, active object
+   if(!iFTReader)
+       {       
+       if(this->FileAccess() && this->FileAccess()->EncodingMode())
+           {
+           iFTReader = CUpnpHttpChunkFileTransferReader::NewL( *this, iSocket,
+                                      iInitialPriority, KFileTransferReaderBufSizeDefault, 
+                   CUpnpHttpChunkFileTransferReader::CalculateBufferSize(
+                            KFileTransferReaderBufSizeDefault,iFileReadBufferSize));
+           }
+       else
+           {
+           iFTReader = CUpnpHttpFileTransferReader::NewL( *this, iSocket,
+                                 iInitialPriority, KFileTransferReaderBufSizeDefault, 
+                       CUpnpHttpChunkFileTransferReader::CalculateBufferSize(
+                            KFileTransferReaderBufSizeDefault,iFileReadBufferSize));      
+           }
+       }       
+   else
+       iFTReader->Reset();
+   
+   iFTReader->SetActivated(ETrue);
+    
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::FileTransferWriterConstructL
+// Creates and activates the File Transfer writer object
+// constructor that can leave. Used from derived classes.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::FileTransferWriterConstructL(TInt aWriteSize)
+    {
+    LOGS1( "%i, CUpnpTcpSession::FileTransferWriterConstructL", iId );
+        
+    // Create filetransfer writer, active object
+   if (!iFTWriter)
+       {        
+     iFTWriter = CUpnpHttpFileTransferWriter::NewL( *this, iSocket,
+                                                  iInitialPriority, aWriteSize);  
+       }       
+   else
+       iFTWriter->Reset();
+   
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::~CUpnpTcpSession
+// C++ default destructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpTcpSession::~CUpnpTcpSession()
+    {
+    delete iTcpReader;
+    delete iTcpWriter;   
+    delete iFTReader;
+    if(iFTWriter)
+        {
+        if(iState != ENotConnected)
+            {
+            iSocket.CancelWrite();
+            }            
+        delete iFTWriter;
+        }    
+
+    delete iTimeoutTimer;
+    delete iReceivedMessage;
+    delete iSocketShutdown;
+    LOGS2( "%i, CUpnpTcpSession::~CUpnpTcpSession() - iState: %i",iId, iState );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::ShutdownStop
+// Disconnect connection
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::ShutdownStop()
+    {
+    LOGS2( "%i, CUpnpTcpSession::ShutdownStop, state %i", iId, iState );
+    iState = EShuttingDownWriteWait;
+    if( !iTcpWriter->IsWriting() && !iTcpWriter->IsRetrying() ) 
+        {
+        iSocketShutdown->ShutdownStop();
+           SetState( EShuttingDown);
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::WriteL
+// Write
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::WriteL( const TDesC8& aBuffer )
+    {
+    LOGS1( "%i, CUpnpTcpSession::WriteL(TDesC8&)", iId );
+
+    iTcpWriter->IssueWriteL( aBuffer );
+
+    StartTimeoutTimer( iContinuedMessageDownload );
+
+    LOGS2( "%i, CUpnpTcpSession::WriteL - HTTP (Serverport %i) *** Writing...",
+            iId, ServerPort() );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::InitialReceiveL
+// Receive
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::InitialReceiveL()
+    {
+    LOGS1( "%i, CUpnpTcpSession::ReceiveL()", iId );
+    if ( ( iState == EConnected ) && ( !iTcpReader->IsActive() ) )
+        {
+        iTcpReader->Start();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::ReceiveL
+// Receive
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::ReceiveL()
+    {      
+    // If session is already close or it will be closed when reading is finisihed
+    if ( IsConnected() && ( iSessionKeepAlive || DownloadOngoing() ) )
+        {
+        if (iFTReader && iFTReader->Activated())
+            {
+            iFTReader->StartL();
+            }
+        else
+            {
+            iTcpReader->Start();
+            }
+        StartTimeoutTimer( iSessionNeedsErrorReply );
+        }             
+    else if ( OutstandingWritings() ) //outstanding TCP writing operations
+        {
+        StartTimeoutTimer( iSessionNeedsErrorReply );
+        }
+    else
+        {
+        StartDisconnect();
+        }
+    }    
+
+  
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::ReceivingCompletedL
+// 
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::ReceivingCompletedL( TDesC8& aBuffer )
+    {
+    LOGS1( "%i, CUpnpTcpSession::ReceivingCompletedL(TDesC8& aBuffer)", iId);
+
+    iTimeoutTimer->Cancel();
+    BufferReceivedL( aBuffer );
+    ReceiveL();            
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::WritingCompletedL
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::WritingCompletedL()
+    {
+    LOGS2( "%i, CUpnpTcpSession::WritingCompletedL() iState %i", iId, iState );
+
+    iTimeoutTimer->Cancel();              
+    
+    switch( iState )
+        {
+        case EConnected:
+            {
+            TInetAddr local;
+            iSocket.LocalName( local );
+            local.SetFamily( KAfInet );
+
+            TInetAddr remote;
+            iSocket.RemoteName( remote );
+            remote.SetFamily( KAfInet );    
+            
+            if( ( iSessionKeepAlive || remote == local ) && !iContinuedMessageDownload )
+                {
+                // 20s timeout without HTTP 408 message
+                StartTimeoutTimer( EFalse );
+                }
+            else if( iContinuedMessageDownload )
+                {
+                // If there is expected content of the POST message after sending
+                // there should be error response after timeout.
+                // 20s timeout with HTTP 408 message
+                StartTimeoutTimer( ETrue );
+                }
+            else
+                {
+                //if no POSTs left in a pipeline
+                if (!iSessionKeepAlive)                   
+                    {
+                    iSessionNeedsErrorReply = EFalse;
+                    StartDisconnect();
+                    }
+                }
+            }           
+                
+            break;
+        case EShuttingDownWriteWait:
+                //after successful writing continue to shutdown
+                ShutdownStop();
+                break;
+        case EDisconnecting:
+            if ( iDisconnectNotification )
+                {
+                NotifyDisconnectL( RemoteHost() );
+                DeleteThisSessionL( this );
+                }
+            else
+                {
+                iSessionNeedsErrorReply = EFalse;
+                StartDisconnect();
+                }
+            break;
+           case EServerBusy:
+               DeleteThisSessionL( this );
+              break;
+        default:
+            LOGS2( "%i, PANIC: CUpnpTcpSession::WritingCompletedL, iState: %i", iId, iState );
+            break;
+
+        }
+    }
+        
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::ServerBusyL
+// Send server busy.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::ServerBusyL()
+    {
+    LOGS1( "%i, CUpnpTcpSession::ServerBusyL()", iId );
+    // no reason for reader to read data
+    iTcpReader->Cancel();
+    if(iFTReader)
+        iFTReader->Cancel();
+    
+    CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL( 
+                        RemoteHost(), 
+                        EHttpServiceUnavailable );
+    CleanupStack::PushL( msg );
+    HBufC8* msgbody = NULL;
+    msgbody = msg->ToStringL();
+
+    CleanupStack::PopAndDestroy(msg);
+    CleanupStack::PushL( msgbody );
+
+    WriteL( *msgbody );
+    CleanupStack::PopAndDestroy(msgbody);
+
+    iState = EServerBusy;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::Id
+// Returns session ID
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpTcpSession::Id()
+    {
+    return iId;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::StartTimeoutTimerL
+// Start timer.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::StartTimeoutTimer( TBool aSessionErrorReplyNeeded )
+    {
+    LOGS2( "%i, CUpnpTcpSession::StartTimeoutTimer, state %i", iId, iState );
+
+        if( !ShuttingDown())
+            {
+            iTimeoutTimer->Cancel();          
+            iTimeoutTimer->After( iTimeoutCurrentValue, EFalse );
+            iSessionNeedsErrorReply = aSessionErrorReplyNeeded;    
+            LOGS2( "%i, CUpnpTcpSession::StartTimeoutTimer session:%i"
+                             , iId, iTimeoutCurrentValue );
+            }
+            else 
+                {
+                // If already session is switched to disconnected state then just delete it.
+                LOGS1( "%i, CUpnpTcpSession::StartTimeoutTimer session disconnected"
+                                , iId );
+                iSessionNeedsErrorReply = EFalse;
+                StartDisconnect();
+                }
+    }
+  
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::StartDisconnectingTimer
+// Start timer.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::StartDisconnectingTimer(TInt aTime)
+    {
+    LOGS2( "%i, CUpnpTcpSession::StartDisconnectingTimer, state %i",
+            iId, iState );
+    StartDisconnect();         
+    iTimeoutTimer->After( aTime, EFalse );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::StartDisconnect
+// Start disconnect session.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::StartDisconnect(TBool aDisconnectNotification)
+    {
+    LOGS2( "%i, CUpnpTcpSession::StartDisconnect, state %i",
+            iId, iState ); 
+
+    iDisconnectNotification = aDisconnectNotification;
+    if( iState == EConnected )
+        SetState( EDisconnecting );
+    iTimeoutTimer->Cancel();
+    TRAPD( err, DisconnectRequestL() );
+    if( err < 0 ) 
+        {
+        ShutdownStop();
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::TimerEventL
+// Timer event.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::TimerEventL( CUpnpNotifyTimer* /*aTimer*/ )
+    {
+    if( iState == EConnected ) iSocketShutdown->MarksTimeout();
+    this->DisconnectRequestL();
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::DisconnectRequestL
+// Handles discnnect request.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::DisconnectRequestL()
+    {
+    LOGS2( "%i, CUpnpTcpSession::DisconnectRequestL -  HTTP (Serverport %i)"
+            , iId, ServerPort() );
+    if (DownloadOngoing() && (iState != EDisconnecting))
+        {
+        if(iExportRetryCounter < KMaxExportRetry)
+            {
+            //restart timer - download ongoing
+            StartTimeoutTimer(ETrue);
+            iExportRetryCounter++;                
+            }
+        else
+            {
+            iSocket.CancelWrite();
+            SetState( ENotConnected );
+                       NotifyDisconnectL( RemoteHost() );
+                       iSessionNeedsErrorReply=EFalse;
+                       DeleteThisSessionL( this );
+            }
+            return;
+        }
+    
+    if ( iSessionNeedsErrorReply && !ShuttingDown() )
+        {
+        LOGS1( "%i, CUpnpTcpSession::DisconnectRequestL - reply 408!", iId );
+
+        CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL( 
+                                                        RemoteHost(), 
+                                                        EHttpRequestTimeout );
+        CleanupStack::PushL( msg );
+        HBufC8* tempBuf = NULL;
+        tempBuf = msg->ToStringL();
+        CleanupStack::PopAndDestroy( msg );
+        CleanupStack::PushL( tempBuf );
+        WriteL( *tempBuf );
+        CleanupStack::PopAndDestroy( tempBuf );
+        SetState( EDisconnecting );
+        NotifyTimeoutL();
+        }
+    else
+        {
+        LOGS1( "%i, CUpnpTcpSession::DisconnectRequestL - no reply!", iId );
+        DeleteThisSessionL( this );
+        }
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::SetState
+// Set state to connected.
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::SetState( TUpnpTcpSessionState aState )
+    {
+    LOGS1( "%i, CUpnpTcpSession::SetState()", iId );
+    iState = aState;
+    switch(iState)
+        {
+            case EConnected:
+            
+                iTcpWriter->SessionConnected( ETrue );                                    
+                break;
+            case EDisconnecting:
+                //outstandings writings
+                iTcpWriter->SessionConnected( ETrue );
+                        
+                break;
+            default:
+                iTcpWriter->SessionConnected( EFalse );
+                if(iFTWriter)
+                    iFTWriter->Cancel();
+                break;        
+                
+        }
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::IsConnected
+// Retrun connection state.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpTcpSession::IsConnected()
+    {
+    return ( iState == EConnected );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::RemoteHost
+// Return remote host address.
+// -----------------------------------------------------------------------------
+//
+TInetAddr& CUpnpTcpSession::RemoteHost()
+    {
+    return iAddr;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::HandleErrorL
+// 
+// -----------------------------------------------------------------------------
+//
+void CUpnpTcpSession::HandleErrorL( TInt aError  )
+    {
+    LOGS2( "%i, CUpnpTcpSession::HandleErrorL( %i )", iId , aError);
+    
+    if ( aError == KErrCancel )
+        {
+        return;    
+        }
+         
+
+    if(!ShuttingDown())
+        {
+        if( iState ==  EShuttingDownWriteWait )
+            {
+            ShutdownStop();
+            return;
+            }
+
+    switch( aError )
+        {
+        case KErrNoMemory:
+            NotifyTimeoutL();
+            CheckConnectionCloseL();
+            iSessionNeedsErrorReply = EFalse;
+            SetState( EDisconnecting );
+            NotifyDisconnectL( RemoteHost() );
+            iDisconnectNotification = EFalse;
+            StartDisconnectingTimer( KErrorTimeout );
+            break;            
+
+        case KErrEof:
+            NotifyTimeoutL();
+            CheckConnectionCloseL();
+            iSessionNeedsErrorReply = EFalse;
+            SetState( EDisconnecting );
+            NotifyDisconnectL( RemoteHost() );
+            DeleteThisSessionL( this );
+            break;
+        
+        case KErrServerBusy:
+            iDisconnectNotification = ETrue;
+            iSessionNeedsErrorReply=EFalse;
+            SocketServerBusyL( RemoteHost() );           
+            StartDisconnect();    
+            break;
+
+        case KErrDisconnected:
+            CheckConnectionCloseL();
+            SetState( EDisconnecting );            
+			iSessionNeedsErrorReply = EFalse;
+			iDisconnectNotification = EFalse;
+			StartDisconnect();
+			break;            
+        case KErrCouldNotConnect:      
+        case KErrHostUnreach:    
+        default:
+            iSessionError = aError;            
+            ShutdownStop();
+            break;
+            }
+        }
+    else
+        {
+        iSocketShutdown->HandleError( aError );
+        }
+
+    }
+ 
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::WaitWriteError
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::WaitRetryError(TInt aError, TBool aStartTimer)
+    {
+    LOGS2( "%i, CUpnpTcpSession::WaitRetryError - %i",
+            iId, aError );
+    iTimeoutTimer->Cancel();
+    if (aStartTimer)
+        StartTimeoutTimer( iContinuedMessageDownload );
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::StartClosingSession
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::StartClosingSession()    
+{    
+    iSessionNeedsErrorReply=EFalse;
+    StartDisconnect( ETrue );    
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::IsPersistentConnection
+// 
+// -----------------------------------------------------------------------------
+//    
+TBool CUpnpTcpSession::IsPersistentConnection()    
+{    
+    return iIsPersistent;
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::IsPersistentConnection
+// 
+// -----------------------------------------------------------------------------
+//    
+CUpnpHttpFileTransferReader* CUpnpTcpSession::FileTransferReader()
+{    
+    return iFTReader;
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::FileTransferWriter
+// 
+// -----------------------------------------------------------------------------
+//    
+CUpnpHttpFileTransferWriter* CUpnpTcpSession::FileTransferWriter()
+{    
+    return iFTWriter;
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::IsPersistentConnection
+// 
+// -----------------------------------------------------------------------------
+//    
+TBool CUpnpTcpSession::OutstandingWritings()    
+{    
+    //whether content being served or outstanding messages to be written to the socket
+    return (FileServeExists() || iTcpWriter->HasWriteRequestsToSend());
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::DownloadOngoing
+// 
+// -----------------------------------------------------------------------------
+//    
+TBool CUpnpTcpSession::DownloadOngoing() 
+{    
+    //whether content being served or outstanding messages to be written to the socket
+    return (FileTransferWriter() && FileTransferWriter()->IsActivated() &&
+                                    !FileTransferWriter()->IsCancelled());
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::TimerCancel
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::TimerCancel()    
+    {
+    iTimeoutTimer->Cancel();    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::ShuttingDown
+// 
+// -----------------------------------------------------------------------------
+//    
+TBool CUpnpTcpSession::ShuttingDown() 
+    {    
+    return (iState == ENotConnected || iState == EShuttingDown );
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::CloseSocketL
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::CloseSocketL()
+    {
+    if( iDisconnectNotification )
+        {
+        NotifyDisconnectL( RemoteHost() );
+        }
+    else
+        {
+        NotifyTimeoutL();
+        }
+    iState = ENotConnected;
+    iSocket.Close();
+    DestroyIt( this );        
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::TimeoutCurrentValue
+// 
+// -----------------------------------------------------------------------------
+//    
+TInt CUpnpTcpSession::TimeoutCurrentValue()
+    {
+    return iTimeoutCurrentValue;
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpTcpSession::CancelTcpReader()
+// 
+// -----------------------------------------------------------------------------
+//    
+void CUpnpTcpSession::CancelTcpReader()
+    {
+    iTcpReader->Cancel();    
+    }    
+
+//  End of File