connectivitylayer/isce/p2prouter_dll/src/p2puserchannel.cpp
changeset 0 63b37f68c1ce
child 5 8ccc39f9d787
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivitylayer/isce/p2prouter_dll/src/p2puserchannel.cpp	Fri Nov 06 17:28:23 2009 +0000
@@ -0,0 +1,802 @@
+/*
+* 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 = 0x00,
+    EP2PUserChannelMemAllocFail1,
+    EP2PUserChannelMemAllocFail2,
+    EP2PUserChannelWrongRequest,
+    EP2PUserChannelWrongRequest1,
+    EP2PUserChannelWrongRequest2,
+    EP2PUserChannelWrongRequest3,
+    EP2PUserChannelWrongRequest4,
+    EP2PUserChannelWrongRequest5,
+    EP2PUserChannelWrongRequest6,
+    EP2PUserChannelWrongRequest7,
+    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,
+    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.
+    TRACE_ASSERT_INFO( anInfo->Length() > 0, ( EP2PUserChannelOverTheArrayLimits | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
+    if( !anInfo || anInfo->Length() == 0 ) return KErrNotSupported;
+    TUint8 protocolId = static_cast<TUint8>( ( *anInfo )[ 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 %d 0x%x>" ), this, iShP2PProtocolId, aReqNo, a1 ) );
+    // Programmer errors.
+    ASSERT_RESET_ALWAYS( aReqNo >= ( TInt ) EMinRequestId, ( EP2PUserChannelWrongRequest3 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
+    ASSERT_RESET_ALWAYS( ( aReqNo <= EP2PLastAsyncRequest || aReqNo == KMaxTInt ), ( EP2PUserChannelWrongRequest4 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
+    // Wrong API usage e.g. called function when interface is not open so panic the client thread.
+    ASSERT_PANIC_USER_THREAD_ALWAYS( ( iShP2PProtocolId < EP2PAmountOfProtocols || EP2PAsyncOpen == aReqNo ), iThread, ( EP2PUserChannelWrongParam2 | EDP2PUserChannelTraceId << KClassIdentifierShift ) );
+    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 ) );
+    //TODO    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
+        )
+    {
+
+// TODO    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->Open( ~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 ) );
+            Close( ~iShP2PProtocolId );
+            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