bluetoothcommsprofiles/btpan/bnep/CSocketWriter.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:12:20 +0200
changeset 4 28479eeba3fb
parent 0 29b1cd4cb562
permissions -rw-r--r--
Revision: 201003

// Copyright (c) 2004-2009 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:
//

/**
 @file
 @internalComponent
*/

#include <bluetooth/logger.h>
#include "CBnepLink.h"
#include "CSocketWriter.h"
#include "bneputils.h"

#ifdef __FLOG_ACTIVE
_LIT8(KLogComponent, LOG_COMPONENT_PAN_BNEP);
#endif

CSocketWriter::CSocketWriter (RInternalSocket& aSocket, CBnepLink& aOwner)
        : CActive(EPriorityHigh), iSocket(aSocket), iBnepLink(aOwner)
    {
    LOG_FUNC
    CActiveScheduler::Add(this); 
    }

/**
   Cancels any pending writes.
   @internalComponent
*/
CSocketWriter::~CSocketWriter()
    {
    LOG_FUNC
    Cancel();
    
    iPendingWriteData.Free();
    }

/**
   Create the socket writer
   @internalComponent
*/ 
CSocketWriter* CSocketWriter::NewL (RInternalSocket& aSocket, CBnepLink& aOwner)
    {
    LOG_STATIC_FUNC
    CSocketWriter* self = new(ELeave) CSocketWriter(aSocket, aOwner);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self; 
    }

/**
   Attempt to write a buffer.
   @return KErrNone if successful or a system-wide error code
   @internalComponent
*/
TInt CSocketWriter::Write (RMBufChain& aChain)
    {
    LOG_FUNC
    if (aChain.Length() > KBnepMTU)
        {
        LOG(_L8("Length greater than expected MTU!"));
        aChain.Free();
        return KErrTooBig;
        }
    if (IsActive())
        {
        if(iQueueSize < KMaxSocketWriterQueueSize)
            {
            iQueue.Append(aChain);
            iQueueSize++;
            return KErrNone;
            }
        else
            {
            LOG(_L8("Bnep::ESocketWriterQueueOverflow"));
            aChain.Free();
            return KErrOverflow;
            }
        }
    LOG1(_L8("Length %d"), aChain.Length());
    
    __ASSERT_DEBUG(iPendingWriteData.IsEmpty(), BnepUtils::Panic(Bnep::ESocketWriterQueueOverflow));
    iPendingWriteData.Assign(aChain);
    iSocket.Write(iPendingWriteData, iStatus);

    SetActive();
    return KErrNone; 
    }

/**
   Does nothing
   @internalComponent
*/ 
void CSocketWriter::ConstructL ()
    {
    LOG_FUNC
    }

/**
   Checks iQueue for outstanding buffers and writes the first
   if it exists.
   @internalComponent
*/ 
void CSocketWriter::RunL ()
    {
    LOG_FUNC
	// Check if the completed write was a success.
	if(iStatus.Int() != KErrNone)
		{
		// The write failed - clear the pending write data.
	    LOG1(_L8("CSocketWriter::RunL completed with error: %d"), iStatus.Int());
		iPendingWriteData.Free();
		}

    __ASSERT_DEBUG(iPendingWriteData.IsEmpty(), BnepUtils::Panic(Bnep::ESocketWriterQueueOverflow));

    if(!iQueue.IsEmpty())
        {
        RMBufChain item;
        //Check on return value of iQueue.Remove() is unnecessary, since we've checked iQueue.IsEmpty()
        static_cast<void>(iQueue.Remove(item));
        iQueueSize--;
        Write(item);
        }
    else
        {
        iQueueSize = 0; // To make sure that we are always in sync
        }
    }

/**
   Cancel write.
   @internalComponent
*/
void CSocketWriter::DoCancel ()
    {
    LOG_FUNC
    iSocket.CancelWrite();
    
    // Free the pending data buffer to aviod asserting when the next Write operation
    // is performed.
    
    iPendingWriteData.Free();
    }