diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/dlnawebserver/src/upnptcpsessionreader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnp/upnpstack/dlnawebserver/src/upnptcpsessionreader.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,265 @@ +/** @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: CUpnpTcpSessionReader is a class responsible for +* asynchronous reading from socket owned by CUpnpTcpSession. +* +*/ + + + +#include "upnptcpsession.h" +#include "upnptcpsessionreader.h" +#define KLogFile _L("DLNAWebServer.txt") +#include "upnpcustomlog.h" +#include "inet6err.h" + +static const TInt KMaxRetryErrors = 5; +static const TInt KRetryWaitTime = 1000000; +static const TInt KTwoSec = 2000000; +static const TInt KOneSec = 1000000; + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::NewL +// Factory method. +// --------------------------------------------------------------------------- +// +CUpnpTcpSessionReader* CUpnpTcpSessionReader::NewL( CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aBufferSize ) + { + CUpnpTcpSessionReader* self = new ( ELeave ) + CUpnpTcpSessionReader( aSession, aSocket, aPriority, aBufferSize ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::CUpnpTcpSessionReader +// C++ constructor. +// --------------------------------------------------------------------------- +// +CUpnpTcpSessionReader::CUpnpTcpSessionReader( CUpnpTcpSession& aSession, + RSocket& aSocket, + TThreadPriority aPriority, + TInt aBufferSize ) + :CActive( aPriority ), + iSocket( aSocket ), + iSession( aSession ), + iBufferSize( aBufferSize ) + { + LOGS1( "%i, CUpnpTcpSessionReader::CUpnpTcpSessionReader", iSession.Id() ); + + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::TcpConstructL +// Two-phased constructor +// constructor that can leave. Used from derived classes. +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::ConstructL() + { + CActiveScheduler::Add( this ); + + iReceiveBuffer.CreateL( iBufferSize ); + + iRetryTimer = CUpnpNotifyTimer::NewL( this ); + iCancelTimer = CUpnpNotifyTimer::NewL( this ); + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::~CUpnpTcpSessionReader +// Destructor. +// --------------------------------------------------------------------------- +// +CUpnpTcpSessionReader::~CUpnpTcpSessionReader() + { + LOGS1( "%i, CUpnpTcpSessionReader::~CUpnpTcpSessionReader", iSession.Id() ); + Cancel(); + + iReceiveBuffer.Close(); + + delete iRetryTimer; + delete iCancelTimer; + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::Start +// Starts reading. +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::Start() + { + LOGS1( "%i, CUpnpTcpSessionReader::Start", iSession.Id() ); + // Initiate a new read from socket into iBuffer + if ( !IsActive() ) + { + IssueRead(); + } + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::DoCancel +// From class CActive. +// Cancels issued reading. +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::DoCancel() + { + LOGS1( "%i, CUpnpTcpSessionReader::DoCancel", iSession.Id() ); + // Cancel asychronous read request + iSocket.CancelRead(); + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::CancelRetry +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::CancelTimers() + { + iRetryTimer->Cancel(); + iCancelTimer->Cancel(); + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::RunL +// From class CActive. +// Function is called as a callback when the issued reading is completed. +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::RunL() + { + LOGS2( "%i, CUpnpTcpSessionReader::RunL(), iStatus %i", + iSession.Id(), iStatus.Int() ); + + // Active object request complete handler + switch ( iStatus.Int() ) + { + case KErrNone: + iRetryErrorCount = 0; + iCancelTimer->Cancel(); + + // Forward read data to HTTPSession + iSession.ReceivingCompletedL( iReceiveBuffer ); + break; + + case KErrCancel: + if(iCancelFromTimer) + { + IssueRead(); + iCancelFromTimer = EFalse; + } + break; + + case KErrNoMemory: + case KErrNotReady: + case KErrInet6AddressExpired: + if( iRetryErrorCount < KMaxRetryErrors ) + { + iRetryTimer->Cancel(); + iRetryTimer->After( KRetryWaitTime * ++iRetryErrorCount, EFalse ); + break; + } + + default: + iSession.HandleErrorL( iStatus.Int() ); + break; + } + } +// ----------------------------------------------------------------------------- +// CUpnpTcpSessionWriter::RunError +// RunError is called when RunL leaves. +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpSessionReader::RunError( TInt aError ) + { + LOGS2( "%i, CUpnpTcpSessionReader::RunError - %d" + , iSession.Id(), aError); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpSessionReader::TimerEventL +// Retry read +// ----------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::TimerEventL( CUpnpNotifyTimer* aTimer ) + { + if( aTimer == iCancelTimer ) + { + iCancelFromTimer = ETrue; + iSocket.CancelRecv(); + } + else if( aTimer == iRetryTimer ) + { + IssueRead(); + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpSessionReader::StartCancelTimer +// ----------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::StartCancelTimer() + { + TInt timeout = iSession.TimeoutCurrentValue(); + iCancelTimer->Cancel(); + + timeout = timeout/2 - KTwoSec; + if( timeout <= 0 ) timeout = KOneSec; + + iCancelTimer->After( timeout, EFalse ); + iCancelFromTimer = EFalse; + } + +// --------------------------------------------------------------------------- +// CUpnpTcpSessionReader::IssueRead +// Issues reading. +// --------------------------------------------------------------------------- +// +void CUpnpTcpSessionReader::IssueRead() + { + LOGS1( "%i, CUpnpTcpSessionReader::IssueRead", iSession.Id()); + // Initiate a new read from socket into iBuffer + if( IsActive() ) + { + LOGS1( "%i, PANIC: CUpnpTcpSessionReader::IssueRead!", iSession.Id() ); + User::Panic( _L("CUpnpTcpSessionReader is active" ), KErrGeneral ); + } + + if( iSession.IsConnected() ) + { + LOGS1( "%i, CUpnpTcpSessionReader::IssueRead" + , iSession.Id()); + + Deque(); + CActiveScheduler::Add(this); + + iReceiveBuffer.Zero(); + + StartCancelTimer(); + + iSocket.RecvOneOrMore( iReceiveBuffer, 0, iStatus, iLen ); + SetActive(); + } + } + + +// End of File