connectivitylayer/isce/p2prouter_dll/src/p2puserchannel.cpp
author mikaruus
Tue, 19 Oct 2010 13:16:20 +0300
changeset 9 8486d82aef45
parent 5 8ccc39f9d787
permissions -rw-r--r--
modemadaptation release 2010wk40


/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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 <kern_priv.h>              // For DMutex
#include "p2puserchannel.h"         // For DP2PUserChannel
#include "msgqueue.h"               // For DMsgQueue 
#include "p2proutertrace.h"         // For C_TRACE, ASSERT_RESET.. and fault codes.
#include "memapi.h"                 // MemApi
#include "p2pdefs.h"                // For EP2PAmountOfProtocols

enum TP2PUserChannelFaults
    {
    EP2PUserChannelMemAllocFail = 0x01,
    EP2PUserChannelMemAllocFail1,
    EP2PUserChannelMemAllocFail2,
    EP2PUserChannelMemAllocFail3,
    EP2PUserChannelMemAllocFail4,
    EP2PUserChannelWrongRequest,
    EP2PUserChannelWrongRequest1,
    EP2PUserChannelWrongRequest2,
    EP2PUserChannelWrongRequest3,
    EP2PUserChannelWrongRequest4,
    EP2PUserChannelWrongRequest5,
    EP2PUserChannelWrongRequest6,
    EP2PUserChannelWrongRequest7,
    EP2PUserChannelWrongRequest8,
    EP2PUserChannelWrongParam,
    EP2PUserChannelWrongParam2,
    EP2PUserChannelProtocolIdNotSpecified,
    EP2PUserChannelOverTheArrayLimits,
    EP2PUserChannelDesWriteFailed,
    EP2PUserChannelSameRequest,
    EP2PUserChannelSameRequest2,
    EP2PUserChannelNullParam,
    EP2PUserChannelNullParam2,
    EP2PUserChannelDesReadFailed,
    EP2PIUserChannelfNotThreadContext,
    EP2PIUserChannelfNotThreadContext2,
    EP2PIUserChannelfNotThreadContext3,
    EP2PIUserChannelfNotThreadContext4,
    EP2PIUserChannelfNotThreadContext5,
    EP2PUserChannelMutexCreateFailed,
    EP2PUserChannelMutexWaitFailed,
    EP2PUserChannelMutexWaitFailed2,
    EP2PUserChannelMutexWaitFailed3,
    EP2PUserChannelMutexWaitFailed4,
    EP2PUserChannelReqQueueOutOfSync,
    EP2PUserChannelReqQueueOutOfSync1,
    EP2PUserChannelReqQueueOutOfSync2,
    EP2PUserChannelReqQueueOutOfSync3,
    EP2PUserChannelReqQueueOutOfSync4,
    EP2PUserChannelReqQueueOutOfSync5,
    EP2PUserChannelReqQueueOutOfSync6,
    EP2PUserChannelReqQueueOutOfSync7,
    EP2PUserChannelReqQueueOverTheLimits,
    EP2PUserChannelReqQueueOverTheLimits2,
    EP2PUserChannelReqQueueOverTheLimits3,
    EP2PUserChannelReqQueueWrongRequest,
    EP2PUserChannelReqQueueWrongRequest2,
    EP2PUserChannelReqQueueMemoryAllocFailure,
    EP2PUserChannelReqQueueCommon,
    };


// Extracting and adding the pipeheader.
const TInt KFirstParam( 0 );
const TInt KSecondParam( 1 );
const TInt KNoParams( KErrNone );
const TInt KOneParam( 1 );
const TInt KTwoParams( 2 );
const TInt KThreeParams( 3 );

const TInt KDestStartOffset( 0 );
const TInt KP2PLddEmptyRxPriori( 1 );
const TInt KP2PLddCompletePriori( 1 );

const TInt KP2PMaximumSendSize( 0xffff );

//DMutex* DP2PUserChannel::iShP2PProtocolIdMutex = NULL;
_LIT8( KP2PUserChannelP2PProtocolIdMutex, "P2PUserChannelP2PProtocolIdMutex" );

//
// user<> kernel interaction() done in LDD DFC thread
// 
// kernel<>kernel interaction() done in Extension DFC thread
//
// DEMAND_PAGING
// Receive (write k>u) is done only in LDD thread context to allow Extension thread to continue when dp swaps.
// Send ((write u>k) is not done at the moment in LDD thread context only. Check is it possible to happend (not to be in usable memory after send (unlikely?)).
DP2PUserChannel::DP2PUserChannel(
        // None
        )
    :
    iShP2PProtocolId( EP2PAmountOfProtocols ),
    iReceiveBufPtr( NULL ),
    iRx( NULL ),
    iP2PReqQueue( NULL ),
    iThread( &Kern::CurrentThread() )
    {

    C_TRACE( ( _T( "DP2PUserChannel::DP2PUserChannel>" ) ) );
    iRouterIf = MP2PChRouterIf::GetIf();
    ASSERT_RESET_ALWAYS( iRouterIf, ( EP2PUserChannelMemAllocFail | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    iEmptyRxQueueDfc = new TDfc( EmptyRxQueueDfc, this, iRouterIf->GetDfcThread( MP2PChRouterIf::EP2PLddDfcThread ), KP2PLddEmptyRxPriori );
    iCompleteChannelRequestDfc = new TDfc( CompleteChReqDfc, this, iRouterIf->GetDfcThread( MP2PChRouterIf::EP2PLddDfcThread ), KP2PLddCompletePriori );
    iP2PReqQueue = new DP2PReqQueue();
    ASSERT_RESET_ALWAYS( iEmptyRxQueueDfc && iCompleteChannelRequestDfc && iP2PReqQueue, ( EP2PUserChannelMemAllocFail1 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    TInt err( Kern::MutexCreate( iShP2PProtocolIdMutex, KP2PUserChannelP2PProtocolIdMutex, KMutexOrdGeneral0 ) );
    ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EP2PUserChannelMutexCreateFailed | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    C_TRACE( ( _T( "DP2PUserChannel::DP2PUserChannel<" ) ) );

    }

DP2PUserChannel::~DP2PUserChannel(
        // None
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x>" ), this, iShP2PProtocolId ) );
    // owned starts
    if( iEmptyRxQueueDfc )
        {
        C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iEmptyRxQueueDfc 0x%x" ), this, iShP2PProtocolId, iEmptyRxQueueDfc ) );
        iEmptyRxQueueDfc->Cancel();
        delete iEmptyRxQueueDfc;
        iEmptyRxQueueDfc = NULL;
        }
    if( iCompleteChannelRequestDfc )
        {
        C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iCompleteChannelRequestDfc 0x%x" ), this, iShP2PProtocolId, iCompleteChannelRequestDfc ) );
        iCompleteChannelRequestDfc->Cancel();
        delete iCompleteChannelRequestDfc;
        iCompleteChannelRequestDfc = NULL;
        }
    if( iRx )
        {
        C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iRx 0x%x" ), this, iShP2PProtocolId, iRx ) );
        delete iRx;
        iRx = NULL;
        }
    if( iReceiveBufPtr )
        {
        C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iReceiveBufPtr 0x%x" ), this, iShP2PProtocolId, iReceiveBufPtr ) );
        iReceiveBufPtr = NULL;
        }
    if( iP2PReqQueue )
       {
       C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iP2PReqQueue 0x%x" ), this, iShP2PProtocolId, iP2PReqQueue ) );
       delete iP2PReqQueue;
       iP2PReqQueue = NULL;
       }
    // No need to check, if failed reseted already
    C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x iShP2PProtocolIdMutex 0x%x" ), this, iShP2PProtocolId, iShP2PProtocolIdMutex ) );
    iShP2PProtocolIdMutex->Close( NULL );
    // owned ends
    iRouterIf = NULL;
    Kern::SafeClose( reinterpret_cast<DObject*&>(iThread), NULL );
    C_TRACE( ( _T( "DP2PUserChannel::~DP2PUserChannel 0x%x 0x%x<" ), this, iShP2PProtocolId ) );

    }

/*
* Executed in user thread context thread inside CS, cannot be pre-empted.
* Channel can not be used before creation, so no need to synch if congesting only btw the creating user thread and one thread.
*/    
TInt DP2PUserChannel::DoCreate(
        TInt, //aUnit,              // No need to use this, we can avoid the limit of 32 channels
        const TDesC8* anInfo,       // Contains the protocolId
        const TVersion& // aVer     // Not used at the moment.
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::DoCreate 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId, anInfo ) );
    if( !Kern::CurrentThreadHasCapability( ECapabilityCommDD, __PLATSEC_DIAGNOSTIC_STRING( "Check by: P2PRouter" ) ) ) return KErrPermissionDenied;  
    TRACE_ASSERT_INFO( anInfo, EP2PUserChannelProtocolIdNotSpecified );
    // Check for channel number inside anInfo.
    TUint8* buffer = reinterpret_cast<TUint8*>( Kern::Alloc( 1 ) );
    
    
    TPtr8* bufferPtr = new TPtr8( buffer, 1 );    
    ASSERT_RESET_ALWAYS( bufferPtr && buffer, EP2PUserChannelMemAllocFail3 | EDP2PUserChannelTraceId << KClassIdentifierShift );
    
    ASSERT_RESET_ALWAYS( KErrNone == Kern::ThreadDesRead( iThread, anInfo, *bufferPtr, 0, KChunkShiftBy0 ), EP2PUserChannelMemAllocFail4 | EDP2PUserChannelTraceId << KClassIdentifierShift );
    ASSERT_RESET_ALWAYS( bufferPtr->Length() > 0 , EP2PUserChannelReqQueueOverTheLimits3 | EDP2PUserChannelTraceId << KClassIdentifierShift);
    
    TUint8 protocolId = static_cast<TUint8>( ( *bufferPtr )[ 0 ] );

    TRACE_ASSERT_INFO( ( protocolId < EP2PAmountOfProtocols ), ( EP2PUserChannelWrongParam | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    if( protocolId >= EP2PAmountOfProtocols ) return KErrNotSupported;
    TInt err( Kern::MutexWait( *iShP2PProtocolIdMutex ) );
    ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EP2PUserChannelMutexWaitFailed | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    // If channel is already used for some protocol.
    if( iShP2PProtocolId != EP2PAmountOfProtocols )
        {
        Kern::MutexSignal( *iShP2PProtocolIdMutex );
        return KErrAlreadyExists;
        }
    iShP2PProtocolId = ~protocolId;
    Kern::MutexSignal( *iShP2PProtocolIdMutex );
    C_TRACE( ( _T( "DP2PUserChannel::DoCreate protocolId 0x%x 0x%x" ), this, iShP2PProtocolId ) );
    iRx = new DMsgQueue( KP2PLddRxQueuSize );
    ASSERT_RESET_ALWAYS( iRx, ( EP2PUserChannelMemAllocFail2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    // Other DFC functions handling user<>kernel copying done in ldd DFC. Ldd DFC function priority is 1.
    SetDfcQ( iRouterIf->GetDfcThread( MP2PChRouterIf::EP2PDfcThread ) );
    iMsgQ.Receive();
    DObject* thread = reinterpret_cast<DObject*>( iThread );
    // Open is needed to increase ref count to calling thread that is decreased in Kern::SafeClose
    // Possible returns KErrNone ? KErrGeneral
    TInt threadOpen( thread->Open() );
    TRACE_ASSERT_INFO( threadOpen == KErrNone, (TUint8)iShP2PProtocolId );
    C_TRACE( ( _T( "DP2PUserChannel::DoCreate 0x%x 0x%x %d<" ), this, iShP2PProtocolId, threadOpen ) );
    return threadOpen;
    
    }

void DP2PUserChannel::HandleMsg(
        TMessageBase* aMsg
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::HandleMsg 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId, aMsg ) );
    TThreadMessage& m= *( static_cast< TThreadMessage* >( aMsg ) );
    TInt id( m.iValue );
    if( static_cast<TInt>( ECloseMsg ) == id )
        {
        C_TRACE( ( _T( "DP2PUserChannel::HandleMsg ECloseMsg 0x%x 0x%x 0x%x" ), this, iShP2PProtocolId, aMsg ) );
        m.Complete( HandleSyncRequest( EP2PClose, NULL ), EFalse );
        }
    else if( KMaxTInt == id )
        {
        C_TRACE( ( _T( "DP2PUserChannel::HandleMsg cancel 0x%x 0x%x 0x%x" ), this, iShP2PProtocolId, aMsg ) );
        DoCancel( id, m.Int0() );
        m.Complete( KErrNone, ETrue );
        }
    else
        {
        ASSERT_RESET_ALWAYS( ( KErrNotFound < id ), ( EP2PUserChannelWrongRequest | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
        C_TRACE( ( _T( "DP2PUserChannel::HandleMsg request 0x%x 0x%x %d 0x%x" ), this, iShP2PProtocolId, id, aMsg ) );
        TInt completeValue( KErrNone );
        TInt ulen( KErrNotFound );
        switch ( id )
            {
            case EP2PClose:
                {
                ulen = KNoParams;
                break;
                }
            case EP2PSend:
            case EP2PAsyncConnectionLost:
                {
                ulen = KOneParam;
                break;
                }
            case EP2PAsyncOpen:
            case EP2PAsyncReceive:
                {
                ulen = KTwoParams;
                break;
                }
            default:
                {
                ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest1 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
                break;
                }
            }
        TUint32* table[ KThreeParams ];
        completeValue = Kern::ThreadRawRead( iThread, m.Ptr0(), table, ulen * sizeof( TAny* ) );
        if( completeValue == KErrNone )
            {
            switch( id )
                {
                // All asynchronous requests.
                case EP2PAsyncOpen:
                case EP2PAsyncReceive:
                case EP2PAsyncConnectionLost:
                    {
                    // No need to check return value in async functions, completed to user
                    HandleAsyncRequest( id, table );
                    break;
                    }
                case EP2PClose:
                case EP2PSend:
                    {
                    completeValue = HandleSyncRequest( id, table );
                    break;
                    }
                default:
                    {
                    ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
                    break;
                    }
                }
            }
        m.Complete( completeValue, ETrue );
        }
    C_TRACE( ( _T( "DP2PUserChannel::HandleMsg 0x%x 0x%x 0x%x<" ), this, iShP2PProtocolId, aMsg ) );

    }

TInt DP2PUserChannel::Request(
        TInt aReqNo,
        TAny* a1,
        TAny* //a2
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::Request 0x%x 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId, aReqNo, a1 ) );
    // Programmer errors.
    ASSERT_RESET_ALWAYS( aReqNo >= ( TInt ) EMinRequestId, ( EP2PUserChannelWrongRequest3 | EDP2PUserChannelTraceId << KClassIdentifierShift | KExtraInfoShift << (TUint8)aReqNo ) );
    ASSERT_RESET_ALWAYS( ( aReqNo <= EP2PLastAsyncRequest || aReqNo == KMaxTInt ), ( EP2PUserChannelWrongRequest4 | EDP2PUserChannelTraceId << KClassIdentifierShift | KExtraInfoShift << (TUint8)aReqNo ) );
    
    if ( iShP2PProtocolId < EP2PAmountOfProtocols )
        {
        // normal activity
        }
    else if ( iShP2PProtocolId > EP2PAmountOfProtocols ) // Open ongoing, not completed 
        {
        ASSERT_PANIC_USER_THREAD_ALWAYS( ( aReqNo == EP2PAsyncOpen                              ||
                                           ( aReqNo == KMaxTInt && (TInt)a1 == EP2PAsyncOpen )   || // cancel open
                                           aReqNo == EP2PClose ),
                                         iThread, ( EP2PUserChannelWrongParam2 | EDP2PUserChannelTraceId << KClassIdentifierShift | KExtraInfoShift << (TUint8)aReqNo ) );
        }
	else
        {
		// Not possible to come here
        ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest8 | EDP2PUserChannelTraceId << KClassIdentifierShift | KExtraInfoShift << (TUint8)aReqNo ) );
        }

    TInt result( KErrNotFound );
    // All request go in kernel context and with ::DoControl call.
    TThreadMessage& m=Kern::Message();
    m.iValue = aReqNo;
    m.iArg[ KFirstParam ] = a1;
    m.iArg[ KSecondParam ] = NULL;
    result = m.SendReceive( &iMsgQ );
    C_TRACE( ( _T( "DP2PUserChannel::Request 0x%x 0x%x %d 0x%x %d<" ), this, iShP2PProtocolId, aReqNo, a1, result ) );
    return result;

    }

///// Functions from MChannelCallback start (from extension binary)
// called in router ext context
void DP2PUserChannel::ConnectionLost()
    {

    C_TRACE( ( _T( "DP2PKernelChannel::ConnectionLost 0x%x 0x%x %d %d 0x%x>" ), this, iShP2PProtocolId ) );
    EnqueChannelRequestCompleteDfc( EP2PAsyncConnectionLost, KErrNotReady );
    ResetQueues();
    //Closing();
    C_TRACE( ( _T( "DP2PKernelChannel::ConnectionLost 0x%x 0x%x %d %d 0x%x<" ), this, iShP2PProtocolId ) );

    }

// called in router ext context
void DP2PUserChannel::EnqueChannelRequestCompleteDfc(
        TInt aRequest,
        TInt aStatusToComplete
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::EnqueChannelRequestCompleteDfc 0x%x 0x%x %d %d>" ), this, iShP2PProtocolId, aRequest, aStatusToComplete ) );
    ASSERT_THREAD_CONTEXT_ALWAYS( ( EP2PIUserChannelfNotThreadContext | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    TP2PReq req( static_cast<TP2PAsyncRequest>( aRequest ), aStatusToComplete );
    if( iP2PReqQueue->Add( req ) )
        {
        TRACE_ASSERT_INFO( !iCompleteChannelRequestDfc->Queued(), (TUint8)iShP2PProtocolId << KProtocolIdShift | (TUint16)aRequest );
        iCompleteChannelRequestDfc->Enque();
        }
    C_TRACE( ( _T( "DP2PUserChannel::EnqueChannelRequestCompleteDfc 0x%x 0x%x %d %d<" ), this, iShP2PProtocolId, aRequest, aStatusToComplete ) );

    }

// This is called in 1...N thread contextes
void DP2PUserChannel::ReceiveMsg(
        const TDesC8& aMessage
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::ReceiveMsg 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId, &aMessage ) );
    // Can only be called from thread context.
    ASSERT_THREAD_CONTEXT_ALWAYS( ( EP2PIUserChannelfNotThreadContext3 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    iRx->Add( aMessage );
    iEmptyRxQueueDfc->Enque();
    C_TRACE( ( _T( "DP2PUserChannel::ReceiveMsg 0x%x 0x%x 0x%x<" ), this, iShP2PProtocolId, &aMessage ) );

    }


///// Functions from MChannelCallback end (from extension binary)

// Run in P2P extension kernel thread context.
void DP2PUserChannel::Close(
        const TUint8 aP2PProtocolId
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::Close 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId, aP2PProtocolId ) );
    if( EP2PAmountOfProtocols != iShP2PProtocolId )
        {
        C_TRACE( ( _T( "DP2PKernelChannel::Close closing 0x%x 0x%x>" ), iShP2PProtocolId, aP2PProtocolId ) );
        iRouterIf->Close( aP2PProtocolId );
        }
    iShP2PProtocolId = EP2PAmountOfProtocols;
    C_TRACE( ( _T( "DP2PUserChannel::Close 0x%x 0x%x 0x%x<" ), this, iShP2PProtocolId, aP2PProtocolId ) );

    }

void DP2PUserChannel::Closing(
        // None
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::Closing 0x%x 0x%x 0x%x>" ), this, iShP2PProtocolId ) );
    ResetQueues();
    TInt err( Kern::MutexWait( *iShP2PProtocolIdMutex ) );
    ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EP2PUserChannelMutexWaitFailed2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    if( EP2PAmountOfProtocols != iShP2PProtocolId )
        {
        // Cancel any outstanding request. // remember in asynch close not to close it asynhronously
        for( TInt i( 0 ); i < EP2PLastAsyncRequest; ++i )
            {
            if( iP2PReqQueue->GetReq( static_cast< TP2PAsyncRequest >( i ) ) )
                {
                C_TRACE( ( _T( "DP2PUserChannel::Closing 0x%x 0x%x EP2PClose req to cancel" ), this, iShP2PProtocolId, i ) );
                DoCancel( KMaxTInt, i );
                }
            }
        Close( iShP2PProtocolId );
        }
    Kern::MutexSignal( *iShP2PProtocolIdMutex );
    C_TRACE( ( _T( "DP2PUserChannel::Closing 0x%x 0x%x 0x%x<" ), this, iShP2PProtocolId ) );

    }

// Run in P2P user channel kernel thread context.
void DP2PUserChannel::CompleteChReqDfc(
        TAny* aPtr
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::CompleteChReqDfc>" ) ) );
    // Make sure that user side is accessed only by ldd DFCThread.
    ASSERT_THREAD_CONTEXT_ALWAYS( ( EP2PIUserChannelfNotThreadContext2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    //    ASSERT_DFCTHREAD_INLDD();
    DP2PUserChannel* chPtr = reinterpret_cast<DP2PUserChannel*>( aPtr );
    C_TRACE( ( _T( "DP2PUserChannel::CompleteChReqDfc 0x%x 0x%x" ), chPtr, chPtr->iShP2PProtocolId ) );
    TP2PReq requ = chPtr->iP2PReqQueue->Get();
    if( EP2PAsyncOpen == requ.iRequest )
        {
        C_TRACE( ( _T( "DP2PUserChannel::CompleteChReqDfc 0x%x 0x%x status %d" ), chPtr, chPtr->iShP2PProtocolId, requ.iCompleteStatus ) );
        // Check of KErrNone and KErrInUse (same object same id open) and in only those cases ~iCh = ~~iCh kernel already has.
        TInt err( Kern::MutexWait( *chPtr->iShP2PProtocolIdMutex ) );
        ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EP2PUserChannelMutexWaitFailed3 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
        TUint8 chNumber( ( KErrNone == requ.iCompleteStatus || KErrInUse == requ.iCompleteStatus ? ~chPtr->iShP2PProtocolId : EP2PAmountOfProtocols ) );
        chPtr->iShP2PProtocolId = chNumber;
        Kern::MutexSignal( *chPtr->iShP2PProtocolIdMutex );
        }
    TRequestStatus* status( chPtr->iP2PReqQueue->GetReq( requ.iRequest ) );
    Kern::RequestComplete( chPtr->iThread, status, requ.iCompleteStatus );
    C_TRACE( ( _T( "DP2PUserChannel::CompleteChReqDfc 0x%x 0x%x req %d status %d" ), chPtr, chPtr->iShP2PProtocolId, requ.iRequest, requ.iCompleteStatus ) );
    chPtr->iP2PReqQueue->SetReq( requ.iRequest, NULL );
    if( !chPtr->iP2PReqQueue->Empty() )
        {
        CompleteChReqDfc( chPtr );
        }
    C_TRACE( ( _T( "DP2PUserChannel::CompleteChReqDfc 0x%x 0x%x<" ), chPtr, chPtr->iShP2PProtocolId ) );

    }

void DP2PUserChannel::EmptyRxQueueDfc(
        TAny* aPtr // Pointer to self
        )
    {

//     ASSERT_DFCTHREAD_INLDD();
    DP2PUserChannel& chTmp = *reinterpret_cast<DP2PUserChannel*>( aPtr );
    C_TRACE( ( _T( "DP2PUserChannel::EmptyRxQueueDfc 0x%x 0x%x>" ), &chTmp, chTmp.iShP2PProtocolId ) );
    if( ( chTmp.iP2PReqQueue->GetReq( EP2PAsyncReceive ) ) && ( chTmp.iRx->Count() > 0 ) )
        {
        TDes8& tmpDes = chTmp.iRx->Get();
        // Write to user address space (iReceiveBufPtr) the content of tmpDes starting from zero offset as 8bit descriptor data.
        TInt writeError( Kern::ThreadDesWrite( chTmp.iThread, chTmp.iReceiveBufPtr, tmpDes, KDestStartOffset, KChunkShiftBy0, chTmp.iThread ) );
        TRACE_ASSERT_INFO( writeError == KErrNone, ( chTmp.iShP2PProtocolId | writeError << KClassIdentifierShift ) );
        C_TRACE( ( _T( "DP2PUserChannel::EmptyRxQueueDfc writing 0x%x k>u 0x%x 0x%x writeError %d length %d" ), &tmpDes, chTmp.iReceiveBufPtr, chTmp.iShP2PProtocolId, writeError, tmpDes.Length() ) );
        TP2PReq req( static_cast<TP2PAsyncRequest>( EP2PAsyncReceive ), writeError );
        if( chTmp.iP2PReqQueue->Add( req ) )
            {
            TRACE_ASSERT( !chTmp.iCompleteChannelRequestDfc->Queued() );
            CompleteChReqDfc( &chTmp );
            }
        MemApi::DeallocBlock( tmpDes );
        }
    else
        {
        C_TRACE( ( _T( "DP2PUserChannel::EmptyRxQueueDfc 0x%x 0x%x rx inactive or no message" ), &chTmp, chTmp.iShP2PProtocolId ) );
        }
    C_TRACE( ( _T( "DP2PUserChannel::EmptyRxQueueDfc 0x%x 0x%x<" ), &chTmp, chTmp.iShP2PProtocolId ) );

    }


void DP2PUserChannel::ResetQueues(
        // None
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::ResetQueues 0x%x 0x%x>" ), this, iShP2PProtocolId ) );
    if( iRx )
        {
        C_TRACE( ( _T( "DP2PUserChannel::ResetQueues 0x%x 0x%x iRx 0x%x" ), this, iShP2PProtocolId, iRx ) );
        while( iRx->Count() )
            {
            MemApi::DeallocBlock( iRx->Get() );
            }
        }
    C_TRACE( ( _T( "DP2PUserChannel::ResetQueues 0x%x 0x%x<" ), this, iShP2PProtocolId ) );

    }

void DP2PUserChannel::HandleAsyncRequest(
        TInt aRequest,
        TAny* a1
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest 0x%x 0x%x %d>" ), this, iShP2PProtocolId, aRequest ) );
    ASSERT_THREAD_CONTEXT_ALWAYS( ( EP2PIUserChannelfNotThreadContext4 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    TUint32* tablePtr = reinterpret_cast<TUint32*>( a1 );
    TRACE_ASSERT_INFO( tablePtr[ KFirstParam ], (TUint16)aRequest );
    TRequestStatus* requestStatus = reinterpret_cast<TRequestStatus*>( tablePtr[ KFirstParam ] );
    // If request already active.
    if( ( iP2PReqQueue->GetReq( static_cast<TP2PAsyncRequest>( aRequest ) ) ) )
        {
        // Fault if request is already pending and the request status pointer is different.
        // Fault prints 0-7bits: request, 8-15bits: ch number, 16-31bits: fault identifier
        // Assert cause request already active.
        TRACE_ASSERT_INFO( 0, ( EP2PUserChannelSameRequest | static_cast<TUint8>( iShP2PProtocolId ) << KProtocolIdShift | static_cast<TUint8>( aRequest ) << KExtraInfoShift ) );
        // Active object should not give same request object twice before completing the first one.
        ASSERT_PANIC_USER_THREAD_ALWAYS( iP2PReqQueue->GetReq( static_cast< TP2PAsyncRequest >( aRequest ) ) == requestStatus, iThread,
                                       ( EP2PUserChannelSameRequest2 | static_cast<TUint8>( iShP2PProtocolId ) << KProtocolIdShift | static_cast<TUint8>( aRequest ) << KExtraInfoShift  ) );
        }
    else
        {
        iP2PReqQueue->SetReq( static_cast<TP2PAsyncRequest>( aRequest ), requestStatus );
        switch ( aRequest )
            {
            case EP2PAsyncOpen:
                {
                C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest 0x%x 0x%x EP2PAsyncOpen" ), this, iShP2PProtocolId ) );
                // Set open to pending to router, router completes it when the interconnection to other point is ready.
                iRouterIf->Connect( ~iShP2PProtocolId, this );
                break;
                }
            case EP2PAsyncReceive:
                {
                iReceiveBufPtr = reinterpret_cast<TAny*>( tablePtr[ KSecondParam ] );
                C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest 0x%x 0x%x EP2PAsyncReceive 0x%x" ), this, iShP2PProtocolId, iReceiveBufPtr ) );
                iEmptyRxQueueDfc->Enque();
                break;
                }
            case EP2PAsyncConnectionLost:
                {
                C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest 0x%x 0x%x EP2PAsyncConnectionLost" ), this, iShP2PProtocolId ) );
                // If the connection is already lost when function is called return immediately.
                // This might happend in between calls to ::Open and ::NotifyClose
                if( !iRouterIf->ConnectionExist( iShP2PProtocolId ) )
                    {
                    EnqueChannelRequestCompleteDfc( EP2PAsyncConnectionLost, KErrNotReady );
                    ResetQueues();
                    //Closing( iP2PProtocolId );
                    }
                break;
                }
            default:
                {
                ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest5 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
                break;
                }
            }
        }
    C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest 0x%x 0x%x %d<" ), this, iShP2PProtocolId, aRequest ) );

    }

TInt DP2PUserChannel::HandleSyncRequest(
        TInt aRequest,
        TAny* a1
        )
    {

    C_TRACE( ( _T( "DP2PUserChannel::HandleSyncRequest 0x%x 0x%x %d>" ), this, iShP2PProtocolId, aRequest ) );
    ASSERT_THREAD_CONTEXT_ALWAYS( ( EP2PIUserChannelfNotThreadContext5 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
    TInt error( KErrNotSupported );
    switch( aRequest )
        {
        case EP2PClose:
            {
            C_TRACE( ( _T( "DP2PUserChannel::HandleSyncRequest 0x%x 0x%x EP2PClose" ), this, iShP2PProtocolId ) );
            Closing();
            error = KErrNone;
            break;
            }
        case EP2PSend:
                {
                C_TRACE( ( _T( "DP2PUserChannel::HandleSyncRequest 0x%x 0x%x EP2PSend" ), this, iShP2PProtocolId ) );
                TUint32* tablePtr = reinterpret_cast<TUint32*>( a1 );
                TAny* firstParam = reinterpret_cast<TAny*>( tablePtr[ KFirstParam ] );
                TRACE_ASSERT_INFO( firstParam, ( (TUint8)iShP2PProtocolId << KProtocolIdShift | ( EP2PUserChannelNullParam2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) ) );
                TInt msgLength( Kern::ThreadGetDesLength( iThread, firstParam ) );
                C_TRACE( ( _T( "DP2PUserChannel::HandleSyncRequest 0x%x 0x%x EP2PSend 0x%x %d" ), this, iShP2PProtocolId, firstParam, msgLength ) );
                if( msgLength > 0 && msgLength < KP2PMaximumSendSize )
                    {
                    TDes8& sendBlock = MemApi::AllocBlock( msgLength );
                    ASSERT_RESET_ALWAYS( KErrNone == Kern::ThreadDesRead( iThread, firstParam, sendBlock, 0, KChunkShiftBy0 ), ( EP2PUserChannelDesReadFailed | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
                    TRACE_ASSERT_INFO( sendBlock.Length() == msgLength, (TUint8)iShP2PProtocolId << KProtocolIdShift );
                    C_TRACE( ( _T( "DP2PUserChannel::HandleAsyncRequest EP2PAsyncSend 0x%x 0x%x 0x%x" ), this, iShP2PProtocolId, &sendBlock ) );
                    error = iRouterIf->Send( sendBlock, iShP2PProtocolId );
                    }
                else
                    {
                    error = ( msgLength > KP2PMaximumSendSize ) ? KErrNoMemory : KErrBadDescriptor;
                    TRACE_ASSERT_INFO( 0, (TUint8)iShP2PProtocolId << KProtocolIdShift | (TUint16)msgLength );
                    }
                break;
                }
        default:
            {
            ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest6 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
            break;
            }
        }
    C_TRACE( ( _T( "DP2PUserChannel::HandleSyncRequest 0x%x 0x%x %d ret %d<" ), this, iShP2PProtocolId, aRequest, error ) );
    return error;

    }

void DP2PUserChannel::DoCancel(
        TInt aRequest,
        TInt aMask )
    {

    C_TRACE( ( _T( "DP2PUserChannel::DoCancel 0x%x 0x%x>" ), this, iShP2PProtocolId ) );
    switch( aMask&aRequest )
        {
        case EP2PAsyncReceive:
            {
            C_TRACE( ( _T( "DP2PUserChannel::DoCancel 0x%x 0x%x EP2PAsyncReceive 0x%x " ), this, iShP2PProtocolId, iReceiveBufPtr ) );
            iReceiveBufPtr = NULL;
            break;
            }
        case EP2PAsyncOpen:
            {
            // Just complete with cancel
            C_TRACE( ( _T( "DP2PUserChannel::DoCancel 0x%x 0x%x EP2PAsyncOpen" ), this, iShP2PProtocolId ) );
            TInt err( Kern::MutexWait( *iShP2PProtocolIdMutex ) );
            ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EP2PUserChannelMutexWaitFailed4 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
            TUint8 protocolId = ( iShP2PProtocolId > EP2PAmountOfProtocols ) ? ~iShP2PProtocolId : iShP2PProtocolId;
            Close( protocolId );
                
            Kern::MutexSignal( *iShP2PProtocolIdMutex );
            break;
            }
        default:
            {
            ASSERT_RESET_ALWAYS( 0, ( EP2PUserChannelWrongRequest7 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
            break;
            }
        }
    EnqueChannelRequestCompleteDfc( aMask&aRequest, KErrCancel );
    C_TRACE( ( _T( "DP2PUserChannel::DoCancel 0x%x 0x%x<" ), this, iShP2PProtocolId ) );

    }

// Internal class start
DP2PUserChannel::TP2PReq::TP2PReq()
:iRequest( EP2PLastAsyncRequest ), iCompleteStatus( KRequestPending )
    {
    }

DP2PUserChannel::TP2PReq::TP2PReq( TP2PAsyncRequest aReq, TInt aStat  )
:iRequest( aReq), iCompleteStatus( aStat )
{
    ASSERT_RESET_ALWAYS( iRequest != EP2PLastAsyncRequest, ( EP2PUserChannelReqQueueOutOfSync | EDP2PReqQueueId << KClassIdentifierShift ) );
    ASSERT_RESET_ALWAYS( iCompleteStatus != KRequestPending, ( EP2PUserChannelReqQueueOutOfSync1 | EDP2PReqQueueId << KClassIdentifierShift ) );
}

DP2PUserChannel::DP2PReqQueue::DP2PReqQueue()
    {
    C_TRACE( ( _T( "DP2PReqQueue::DP2PReqQueue 0x%x %d>" ), this ) );
    iQueueMutex = new NFastMutex();
    ASSERT_RESET_ALWAYS( iQueueMutex, ( EP2PUserChannelReqQueueMemoryAllocFailure | EDP2PReqQueueId << KClassIdentifierShift ) );
    iSize = EP2PLastAsyncRequest;
    ASSERT_RESET_ALWAYS( ( iSize > 0 ), ( EP2PUserChannelReqQueueOutOfSync2 | EDP2PReqQueueId << KClassIdentifierShift ) );
    iShInputIndex = 0;
    iShOutputIndex = 0;
    iShCount = 0;
    for( TInt i( 0 ); i < iSize; ++i )
        {
        iShReqRingBuffer[ i ].iRequest = EP2PLastAsyncRequest;
        iShReqRingBuffer[ i ].iCompleteStatus = KRequestPending;
        iShReqList[ i ] = NULL;
        }    
    C_TRACE( ( _T( "DP2PReqQueue::DP2PReqQueue 0x%x<" ), this ) );
    }

DP2PUserChannel::DP2PReqQueue::~DP2PReqQueue()
    {
    C_TRACE( ( _T( "DP2PReqQueue::~DP2PReqQueue 0x%x %d>" ), this, iShCount ) );
    // NOTE! This don't deallocate the blocks from the allocated memory just the pointers!
    ASSERT_RESET_ALWAYS( iShCount == 0, ( EP2PUserChannelReqQueueOutOfSync3 | EDP2PReqQueueId << KClassIdentifierShift ) );
    for( TInt i( 0 ); i < iSize; ++i )
        {
        iShReqRingBuffer[ i ].iRequest = EP2PLastAsyncRequest;
        iShReqRingBuffer[ i ].iCompleteStatus = KRequestPending;
        iShReqList[ i ] = NULL;
        }
    iSize = 0;
    iShInputIndex = 0;
    iShOutputIndex = 0;
    iShCount = 0;
    if( iQueueMutex )
        {
        C_TRACE( ( _T( "DP2PReqQueue::~DP2PReqQueue iQueueMutex" ) ) );
        delete iQueueMutex;
        iQueueMutex = NULL;
        }
    C_TRACE( ( _T( "DP2PReqQueue::~DP2PReqQueue 0x%x<" ), this ) );
    }

/* 
* In case of queue overflow throw kern::fault
*/
TBool DP2PUserChannel::DP2PReqQueue::Add( TP2PReq aReq )
    {
    C_TRACE( ( _T( "DP2PReqQueue::Add 0x%x %d %d %d %d>" ), this, iSize, iShCount, iShInputIndex, iShOutputIndex ) );
    TBool ok( EFalse );
    NKern::FMWait( iQueueMutex );
    // If queue get's overfilled throw kernel fault.
    ASSERT_RESET_ALWAYS( ( iShCount < iSize ), ( EP2PUserChannelReqQueueOutOfSync4 | EDP2PReqQueueId << KClassIdentifierShift ) );
    ASSERT_RESET_ALWAYS( EP2PLastAsyncRequest > aReq.iRequest, ( EP2PUserChannelReqQueueOverTheLimits | EDP2PReqQueueId << KClassIdentifierShift ) );
    if( iShReqList[ aReq.iRequest ] )
        {
        // Place the buffer into the queue.
        iShReqRingBuffer[ iShInputIndex ] = aReq;
        // Adjust input pointer.
        iShInputIndex = ( ( iShInputIndex + 1 ) % iSize );
        // Remember the amount of the requests in the queue.
        iShCount++;
        ok = ETrue;
        }
    NKern::FMSignal( iQueueMutex );
    C_TRACE( ( _T( "DP2PReqQueue::Add 0x%x %d %d %d %d %d<" ), this, iSize, iShCount, iShInputIndex, iShOutputIndex, ok ) );
    return ok;
    }

/*
*Returns the first pointer ( iShOutputIndex ) from the ring buffer.
*/
TBool DP2PUserChannel::DP2PReqQueue::Empty()
    {
    C_TRACE( ( _T( "DP2PReqQueue::Empty 0x%x %d<>" ), this, iShCount ) );
    return iShCount == 0 ?  ETrue : EFalse;

    }

/*
*Returns the first pointer ( iShOutputIndex ) from the ring buffer.
*/
DP2PUserChannel::TP2PReq DP2PUserChannel::DP2PReqQueue::Get()
    {
    C_TRACE( ( _T( "DP2PReqQueue::Get 0x%x %d %d %d %d>" ), this, iSize, iShCount, iShInputIndex, iShOutputIndex ) );
    NKern::FMWait( iQueueMutex );
    // If queue is empty.
    ASSERT_RESET_ALWAYS( ( iShCount > 0 ), ( EP2PUserChannelReqQueueOutOfSync5 | EDP2PReqQueueId << KClassIdentifierShift ) );
    // Get the buffer from the queue.
    ASSERT_RESET_ALWAYS( EP2PLastAsyncRequest > iShOutputIndex, ( EP2PUserChannelReqQueueOverTheLimits2 | EDP2PReqQueueId << KClassIdentifierShift ) );
    TP2PReq temp = iShReqRingBuffer[ iShOutputIndex ];
    // Set buffer location to NULL.
    iShReqRingBuffer[ iShOutputIndex ].iRequest = EP2PLastAsyncRequest;
    iShReqRingBuffer[ iShOutputIndex ].iCompleteStatus = KRequestPending;
    // Adjust output pointer.
    iShOutputIndex = ( ( iShOutputIndex + 1 ) % iSize );
    // Remember the amount of the requests in the queue.
    iShCount--;
    NKern::FMSignal( iQueueMutex );
    ASSERT_RESET_ALWAYS( temp.iRequest != EP2PLastAsyncRequest, ( EP2PUserChannelReqQueueOutOfSync6 | EDP2PReqQueueId << KClassIdentifierShift ) );
    ASSERT_RESET_ALWAYS( temp.iCompleteStatus != KRequestPending, ( EP2PUserChannelReqQueueOutOfSync7 | EDP2PReqQueueId << KClassIdentifierShift ) );
    C_TRACE( ( _T( "DQueue::Get 0x%x %d %d %d %d<" ), this, iSize, iShCount, iShInputIndex, iShOutputIndex ) );
    return temp;
    }

/*
* Set req active / deactive. Default deactive.
*/
void DP2PUserChannel::DP2PReqQueue::SetReq( TP2PAsyncRequest aReqToSet, TRequestStatus* aStatus )
    {
    C_TRACE( ( _T( "DP2PReqQueue::SetReq 0x%x %d 0x%x>" ), this, aReqToSet, aStatus ) );
    ASSERT_RESET_ALWAYS( aReqToSet < EP2PLastAsyncRequest, ( EP2PUserChannelReqQueueWrongRequest | EDP2PReqQueueId << KClassIdentifierShift ) );
    // If setting same request twice.
    C_TRACE( ( _T( "DP2PReqQueue::SetReq 0x%x %d 0x%x 0x%x TBR" ), this, aReqToSet, aStatus, iShReqList[ aReqToSet ] ) );
    ASSERT_RESET_ALWAYS( !( !iShReqList[ aReqToSet ] && aStatus == NULL ), EP2PUserChannelReqQueueCommon );
    iShReqList[ aReqToSet ] = aStatus;
    C_TRACE( ( _T( "DP2PReqQueue::SetReq 0x%x %d 0x%x<" ), this, aReqToSet, aStatus ) );
    }

/*
* Set req active / deactive. Default deactive.
*/
TRequestStatus* DP2PUserChannel::DP2PReqQueue::GetReq( TP2PAsyncRequest aReqToGet )
    {
    ASSERT_RESET_ALWAYS( aReqToGet < EP2PLastAsyncRequest, ( EP2PUserChannelReqQueueWrongRequest2 | EDP2PReqQueueId << KClassIdentifierShift ) );
    C_TRACE( ( _T( "DP2PReqQueue::GetReq 0x%x 0x%x %d<>" ), this, iShReqList[ aReqToGet ], aReqToGet ) );
    TRequestStatus* tmpStatus = iShReqList[ aReqToGet ];
    return tmpStatus;
    }
// Internal class end