www.pudn.com > sockets.rar > socketswriter.cpp


/* Copyright (c) 2004, Nokia. All rights reserved */ 
 
 
// INCLUDE FILES 
#include "SocketsWriter.h" 
#include "TimeOutTimer.h" 
#include "Sockets.pan" 
#include "EngineNotifier.h" 
 
// STATIC MEMBER INITIALISATIONS 
const TInt CSocketsWriter::KTimeOut = 30000000; // 30 seconds time-out 
 
// ========================= MEMBER FUNCTIONS ================================== 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::NewL() 
// Two-phased constructor. 
// ----------------------------------------------------------------------------- 
// 
CSocketsWriter* CSocketsWriter::NewL( MEngineNotifier& aEngineNotifier, 
                                      RSocket& aSocket ) 
    { 
    CSocketsWriter* self = CSocketsWriter::NewLC( aEngineNotifier, 
                                                  aSocket ); 
    CleanupStack::Pop( self ); 
    return self; 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::NewLC() 
// Two-phased constructor. 
// ----------------------------------------------------------------------------- 
// 
CSocketsWriter* CSocketsWriter::NewLC( MEngineNotifier& aEngineNotifier, 
                                       RSocket& aSocket ) 
    { 
    CSocketsWriter* self = new ( ELeave ) CSocketsWriter( aEngineNotifier, 
                                                          aSocket ); 
    CleanupStack::PushL( self ); 
    self->ConstructL(); 
    return self; 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::CSocketsWriter() 
// C++ default constructor can NOT contain any code, that might leave. 
// ----------------------------------------------------------------------------- 
// 
CSocketsWriter::CSocketsWriter( MEngineNotifier& aEngineNotifier, 
                                RSocket& aSocket ) 
: CActive( EPriorityStandard ), 
  iSocket( aSocket ), 
  iEngineNotifier( aEngineNotifier ) 
    { 
    // No implementation required 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::ConstructL() 
// Symbian 2nd phase constructor can leave. 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::ConstructL() 
    { 
    CActiveScheduler::Add( this ); 
 
    iTimeOut = KTimeOut; 
    iTimer = CTimeOutTimer::NewL( CActive::EPriorityUserInput, *this ); 
    iWriteStatus = EWaiting; 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::~CSocketsWriter() 
// Destructor. 
// ----------------------------------------------------------------------------- 
// 
CSocketsWriter::~CSocketsWriter() 
    { 
    Cancel(); 
    delete iTimer; 
    iTimer = NULL; 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::DoCancel() 
// Cancels any outstanding operation. 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::DoCancel() 
    { 
    // Cancel asychronous write request 
    iSocket.CancelWrite(); 
    iTimer->Cancel(); 
    iWriteStatus = EWaiting; 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::RunL() 
// Called when operation completes. 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::RunL() 
    { 
    iTimer->Cancel(); 
 
    // Active object request complete handler 
    if ( iStatus == KErrNone ) 
        { 
        switch( iWriteStatus ) 
            { 
            // Character has been written to socket 
            case ESending: 
                SendNextPacket(); 
                break; 
            default: 
                User::Panic( KPanicSocketsEngineWrite, ESocketsBadStatus ); 
                break; 
            }; 
        } 
    else 
        { 
        // Error: pass it up to user interface 
        iEngineNotifier.ReportError( MEngineNotifier::EGeneralWriteError, 
                                     iStatus.Int() ); 
        iWriteStatus = EWaiting; 
        } 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::TimerExpired() 
// Handles a timeout event. 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::TimerExpired() 
    { 
    Cancel(); 
    iWriteStatus = EWaiting; 
    iEngineNotifier.ReportError( MEngineNotifier::ETimeOutOnWrite,  
                                 KErrTimedOut ); 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::IssueWriteL() 
// Writes the data to the socket ( buffered ). 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::IssueWriteL( const TDesC8& aData ) 
    { 
    if ( ( iWriteStatus != EWaiting ) && ( iWriteStatus != ESending ) ) 
        { 
        User::Leave( KErrNotReady ); 
        } 
 
    if ( ( aData.Length() + iTransferBuffer.Length() ) > 
         iTransferBuffer.MaxLength() ) 
        { 
        // Not enough space in buffer 
        User::Leave( KErrOverflow ); 
        } 
 
    // Add new data to buffer 
    iTransferBuffer.Append( aData ); 
 
    if ( !IsActive() ) 
        { 
        SendNextPacket(); 
        } 
    } 
 
// ----------------------------------------------------------------------------- 
// CSocketsWriter::SendNextPacket() 
// Handles a 'write buffer empty' situation. 
// ----------------------------------------------------------------------------- 
// 
void CSocketsWriter::SendNextPacket() 
    { 
    if ( iTransferBuffer.Length() > 0 ) 
        { 
        // Move data from transfer buffer to actual write buffer 
        iWriteBuffer = iTransferBuffer; 
        iTransferBuffer.Zero(); 
        iSocket.Write( iWriteBuffer, iStatus ); // Initiate actual write 
 
        iWriteStatus = ESending; 
        // Request timeout 
        iTimer->After( iTimeOut ); 
        SetActive(); 
        } 
    else 
        { 
        iWriteStatus = EWaiting; 
        } 
    } 
 
// End of File