Msrp/MsrpServer/src/CMSRPServerSubSession.cpp
branchMSRP_FrameWork
changeset 25 505ad3f0ce5c
child 58 cdb720e67852
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Msrp/MsrpServer/src/CMSRPServerSubSession.cpp	Sat Jun 12 14:30:11 2010 +0530
@@ -0,0 +1,600 @@
+/*
+* Copyright (c) 2009-2010 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:
+* MSRP Implementation
+*
+*/
+
+
+#include "MSRPCommon.h"
+#include "MSRPServerCommon.h"
+#include "CMSRPServerSubSession.h"
+#include "MMSRPConnectionManager.h"
+#include "CMSRPServerSession.h"
+#include "CMSRPMessageBase.h"
+#include "MMSRPConnection.h"
+#include "CMSRPMessageHandler.h"
+#include "CMSRPResponse.h"
+#include "s32mem.h"
+#include "CMSRPMessage.h"
+#include "TStateFactory.h"
+#include "TStates.h"
+#include "CMsrpToPathHeader.h"
+#include "CMSRPFromPathHeader.h"
+
+
+CRMessageContainer::CRMessageContainer()
+    {
+    iStatus = FALSE;
+    }
+
+CRMessageContainer::~CRMessageContainer()
+    {
+    
+    }
+
+TInt CRMessageContainer::Write(TInt aParam,const TDesC8& aDes,TInt aOffset) const
+    {
+    // Write the data, change status and complete the RMessage.
+    return iMsg.Write(aParam, aDes, aOffset);        
+    }
+
+void CRMessageContainer:: ReadL(TInt aParam,TDes8& aDes,TInt aOffset) const
+    {
+    // Write the data, change status and complete the RMessage.
+    return iMsg.ReadL(aParam, aDes, aOffset);        
+    }
+
+void CRMessageContainer::Complete(TInt aReason)
+    {
+    iStatus = FALSE;
+    iMsg.Complete(aReason);    
+    }
+
+TBool CRMessageContainer::Check()
+    {
+    return iStatus;
+    }
+
+TBool CRMessageContainer::set(const RMessage2& aMessage)
+    {    
+    if(FALSE == iStatus)
+        {
+        iMsg = aMessage; // Exclicit copy.
+        iStatus = TRUE;
+        return iStatus;        
+        }
+    else
+        {
+        MSRPLOG("CRMessageContainer::set Error!! Container already full");
+        return FALSE;
+        }    
+    }
+
+CMSRPServerSubSession* CMSRPServerSubSession::NewL( CMSRPServerSession& aServerSession, CStateFactory& aStateFactory )
+    {
+    CMSRPServerSubSession* self = 
+        CMSRPServerSubSession::NewLC( aServerSession, aStateFactory );
+
+    CleanupStack::Pop(self);
+    return self;    
+    }    
+
+
+CMSRPServerSubSession* CMSRPServerSubSession::NewLC( CMSRPServerSession& aServerSession,CStateFactory& aStateFactory )
+    {
+    
+    CMSRPServerSubSession* self =
+                            new (ELeave) CMSRPServerSubSession( aServerSession, aStateFactory );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+
+CMSRPServerSubSession::CMSRPServerSubSession( CMSRPServerSession& aServerSession,CStateFactory& aStateFactory )
+                         : iServerSession(aServerSession), iStateFactory(aStateFactory)
+                                              
+    {
+    }
+
+
+CMSRPServerSubSession::~CMSRPServerSubSession()
+    {
+    MSRPLOG("CMSRPServerSubSession::~CMSRPServerSubSession Entered");
+    
+    iState = NULL;         
+
+    iOutMsgQ.Destroy();
+    iInCommingMsgQ.Destroy();
+    iPendingSendMsgQ.Destroy();
+    iPendingForDeletionQ.Destroy();
+
+    QueueLog();
+
+    if(iCurrentMsgHandler)
+        {
+        delete iCurrentMsgHandler;
+        iCurrentMsgHandler = NULL;
+        }
+    
+    if(iConnection)
+        {
+        iConnection->ReleaseConnection(*this);
+        iConnection = NULL;
+        }
+
+    if(iLocalSessionID)
+        {
+        delete iLocalSessionID;
+        iLocalSessionID = NULL;
+        }
+
+    if( iRemoteSessionID )
+        {
+        delete iRemoteSessionID;
+        iRemoteSessionID = NULL;
+        }
+
+    if( iReceivedResp )
+        {
+        delete iReceivedResp;
+        iReceivedResp = NULL;
+        }
+    if( iReceiveFileMsgHdler )
+        {
+        delete iReceiveFileMsgHdler;
+        iReceiveFileMsgHdler = NULL;
+        }
+
+    MSRPLOG("CMSRPServerSubSession::~CMSRPServerSubSession Exit");
+    }
+
+
+void CMSRPServerSubSession::ConstructL( )
+    {
+    // Not the place where this should be done!!
+    MSRPLOG("CMSRPServerSubSession::ConstructL");  
+    iState = iStateFactory.getStateL( EIdle );
+    iLocalSessionID = CreateSubSessionIDL();    
+    }
+
+
+HBufC8* CMSRPServerSubSession::CreateSubSessionIDL( )
+    {
+    MSRPLOG("CMSRPServerSubSession::CreateSubSessionIDL");
+    HBufC8 *sessID = HBufC8::NewLC(KMSRPSessIdLength);
+    TInt64 randSeed(Math::Random());
+    TInt rand;
+          
+    /* Append Random bits using two Random strings */
+    rand = Math::Rand(randSeed);
+    (sessID->Des()).AppendNumFixedWidth(rand,EHex,KMSRPSessIdLength/2);
+    rand = Math::Rand(randSeed);
+    (sessID->Des()).AppendNumFixedWidth(rand,EHex,KMSRPSessIdLength/2);
+        
+    CleanupStack::Pop(1);// sessID
+    return sessID;
+    }
+
+
+TBool CMSRPServerSubSession::ProcessEventL( TMSRPFSMEvent aEvent)
+    {
+    // Call the relevant state. Setup Traps for graceful error propagation to the client.
+    MSRPLOG("CMSRPServerSubSession::ProcessEventL() Entered");
+
+    QueueLog();    
+            
+    iState = iState->EventL(aEvent, this); 
+    
+    MSRPLOG("CMSRPServerSubSession::ProcessEventL() Exit ");
+    return TRUE;
+    }
+
+
+TBool CMSRPServerSubSession::ServiceL( const RMessage2& aMessage )
+    {
+    MSRPLOG("CMSRPServerSubSession::ServiceL()");
+
+    // Process Client Server functions to FSM Events.
+
+    // Getting rid of the switch for translation.
+    TMSRPFSMEvent event = (TMSRPFSMEvent) (aMessage.Function() - 2); 
+
+    // Store the incomming aMessage to form the context of the state machine.
+    iClientMessage = &aMessage;        
+        
+    return ProcessEventL(event);    
+    }
+
+
+MMSRPConnectionManager& CMSRPServerSubSession::ConnectionManager( )
+    {
+    return iServerSession.ConnectionManager();
+    }
+
+
+// Implementation of interfaces from MMSRPConnectionObserver.
+void CMSRPServerSubSession::ConnectionStateL( TInt /*aNewState*/, TInt /*aStatus*/ )
+    {    
+    ProcessEventL(EConnectionStateChangedEvent);
+    }
+
+
+TBool CMSRPServerSubSession::MessageReceivedL( CMSRPMessageHandler* aMsg )
+    {
+    MSRPLOG("CMSRPServerSubSession::MessageReceivedL - New message received");
+    TBool retVal = FALSE;
+    if(checkMessageForSelfL(aMsg))
+        {           
+        iReceivedMsg = aMsg;
+        ProcessEventL(EMSRPIncomingMessageReceivedEvent);
+        retVal = TRUE;
+        }
+
+    return retVal;    
+    }
+
+
+void CMSRPServerSubSession::UnclaimedMessageL( CMSRPMessageHandler* aMsg )
+    {
+    MSRPLOG("CMSRPServerSubSession::UnclaimedMessage - Unclaimed message received!!");
+    
+    if( (aMsg->MessageType() == MMSRPIncomingMessage::EMSRPMessage ||
+            aMsg->MessageType() == MMSRPIncomingMessage::EMSRPNotDefined )
+            && EFalse == matchSessionIDL(aMsg->GetIncomingMessage()->ToPathHeader()))
+        {        
+        TBool sendToClient = aMsg->SendResponseL(this, *iConnection, 
+                CMSRPResponse::ESessionDoesNotExist);          
+        iPendingForDeletionQ.Queue(*aMsg);
+        }
+    else
+        {
+        delete aMsg; 
+        }    
+    }
+
+
+// Implementation of interface from MMSRPMsgObserver.
+
+void CMSRPServerSubSession::MessageSendCompleteL()
+    {
+    // Called when a message is fully sent out.
+    ProcessEventL(EMSRPDataSendCompleteEvent);
+    }
+
+void CMSRPServerSubSession::MessageResponseSendCompleteL(CMSRPMessageHandler& aMsg)
+    {
+    // Called when a message is fully sent out.
+    // Common event handling.
+    iReceivedResp = &aMsg;
+    if(iFileShare)
+        {        
+        ProcessEventL(EMSRPResponseSendCompleteEvent);
+        }
+        if(iPendingForDeletionQ.explicitRemove(iReceivedResp))
+            {
+            delete iReceivedResp;
+            iReceivedResp = NULL;
+            }
+        
+    }
+
+
+void CMSRPServerSubSession::MessageSendProgressL(TInt aBytesSent, TInt aTotalBytes)
+    {
+    iBytesTransferred = aBytesSent;
+    iTotalBytes = aTotalBytes;
+    ProcessEventL(EMSRPSendProgressEvent);    
+    }
+
+
+void CMSRPServerSubSession::MessageReceiveProgressL(TInt aBytesRecvd, TInt aTotalBytes)
+    {
+    iBytesTransferred = aBytesRecvd;
+    iTotalBytes = aTotalBytes;
+    ProcessEventL(EMSRPReceiveProgressEvent);    
+    }
+
+
+void CMSRPServerSubSession::WriterError()
+    {
+    
+    }
+
+
+// Utility Stuff - Common functions used often by States.
+void CMSRPServerSubSession::CompleteClient(TInt aReason)
+    {
+    iClientMessage->Complete(aReason);
+    iClientMessage = NULL;
+    }
+
+TInt CMSRPServerSubSession::Write(TInt aParam,const TDesC8& aDes)
+    {
+    TInt retVal = iClientMessage->Write(aParam, aDes);  
+    return retVal; 
+    }
+
+
+TBool CMSRPServerSubSession::QueueClientSendRequestsL()
+    {
+    // Generic function to Queue the client send requests message. Would be used by 
+    // many states to add to the pending client requests queue.
+    MSRPLOG("CMSRPServerSubSession::QueueClientSendRequestsL");
+        
+    const RMessage2* aMessage = iClientMessage;
+    iClientMessage = NULL;
+
+    aMessage->ReadL( 0, iSendMSRPdataPckg);
+
+    CMSRPMessageHandler *aMessageHandler 
+        = CMSRPMessageHandler::NewL(this,
+            iSendMSRPdataPckg().iExtMessageBuffer); 
+    
+    iPendingSendMsgQ.Queue(*aMessageHandler);    
+    aMessage->Complete( KErrNone );        
+        return TRUE;            
+    }
+
+
+void CMSRPServerSubSession::NotifyFileReceiveResultToClientL(CMSRPMessageHandler */*msgHandler*/)
+    {
+    //TODO
+    MSRPLOG("CMSRPServerSubSession::NotifyFileReceiveResultToClientL enter");
+    iSendResultListenMSRPDataPckg().iStatus = 200;
+    iSendResultListenMSRPDataPckg().iIsProgress = FALSE;
+    iResponseListner.Write(0,iSendResultListenMSRPDataPckg);
+    iResponseListner.Complete( KErrNone );
+    MSRPLOG("CMSRPServerSubSession::NotifyFileReceiveResultToClientL exit");
+    }
+
+
+void CMSRPServerSubSession::NotifyFileSendResultToClientL(CMSRPMessageHandler */*msgHandler*/)
+    {
+    //TODO
+    MSRPLOG("CMSRPServerSubSession::NotifyFileSendResultToClientL enter");
+    iSendResultListenMSRPDataPckg().iStatus = 200;
+    iSendResultListenMSRPDataPckg().iIsProgress = FALSE;
+    iResponseListner.Write(0,iSendResultListenMSRPDataPckg);
+    iResponseListner.Complete( KErrNone );
+    MSRPLOG("CMSRPServerSubSession::NotifyFileSendResultToClientL exit");
+    }
+
+
+TBool CMSRPServerSubSession::SendProgressToClientL(CMSRPMessageHandler */*msgHandler*/)
+    {
+    MSRPLOG("CMSRPServerSubSession::SendProgressToClientL enter");
+    iSendResultListenMSRPDataPckg().iStatus    = KErrNone;
+    iSendResultListenMSRPDataPckg().iIsProgress = TRUE;
+    iSendResultListenMSRPDataPckg().iBytesSent = iBytesTransferred;
+    iSendResultListenMSRPDataPckg().iTotalBytes = iTotalBytes;
+    
+    iResponseListner.Write(0,iSendResultListenMSRPDataPckg);
+    iResponseListner.Complete( KErrNone );
+
+    MSRPLOG("CMSRPServerSubSession::SendProgressToClientL exit");
+    return TRUE;
+    }
+
+
+TBool CMSRPServerSubSession::ReceiveProgressToClientL(CMSRPMessageHandler */*msgHandler*/)
+    {
+    MSRPLOG("CMSRPServerSubSession::ReceiveProgressToClientL enter");
+    iListenMSRPdataPckg().iStatus    = KErrNone;
+    iListenMSRPdataPckg().iIsProgress = TRUE;
+    iListenMSRPdataPckg().iBytesRecvd = iBytesTransferred;
+    iListenMSRPdataPckg().iTotalBytes = iTotalBytes;
+    
+    iIncommingMessageListner.Write(0,iListenMSRPdataPckg);
+    iIncommingMessageListner.Complete( KErrNone );
+    MSRPLOG("CMSRPServerSubSession::ReceiveProgressToClientL exit");
+    return TRUE;
+    }
+
+
+TBool CMSRPServerSubSession::sendResultToClientL(CMSRPMessageHandler *msgHandler)
+    {
+    MSRPLOG("CMSRPServerSubSession::sendResultToClientL");
+    HBufC8* messageId = NULL;
+    TUint i=0;
+
+    // Allocates memory.
+    TBool error = msgHandler->GetSendResultL( i, messageId );            
+
+    iSendResultListenMSRPDataPckg().iIsProgress = FALSE;
+    iSendResultListenMSRPDataPckg().iMessageId = *messageId;
+    iSendResultListenMSRPDataPckg().iStatus    = i;
+    iResponseListner.Write(0,iSendResultListenMSRPDataPckg);
+
+    delete messageId;
+    iResponseListner.Complete( KErrNone );
+    return error;
+    }
+
+
+TBool CMSRPServerSubSession::sendMsgToClientL(CMSRPMessageHandler *incommingMsgHandler)
+    {
+    // Use the client send result listner to respond.
+    // Extract the data and complete the iIncommingMessageListner.
+    MSRPLOG("CMSRPServerSubSession::sendMsgToClientL");
+    CMSRPMessage* inMsg = incommingMsgHandler->GetIncomingMessage();
+
+    CBufSeg* buf1 = CBufSeg::NewL( 256 ); // expandsize 256
+    CleanupStack::PushL( buf1 );
+    RBufWriteStream writeStream( *buf1 );
+    CleanupClosePushL( writeStream );
+
+    inMsg->ExternalizeL( writeStream );
+    writeStream.CommitL();
+
+    iListenMSRPdataPckg().iIsProgress = FALSE;
+    if ( buf1->Size() > KMaxLengthOfIncomingMessageExt )
+        {
+        // invalid message size
+        iListenMSRPdataPckg().iStatus = KErrArgument;
+        }
+    else
+        {
+        buf1->Read( 0, iListenMSRPdataPckg().iExtMessageBuffer, buf1->Size() );
+            iListenMSRPdataPckg().iStatus = KErrNone;            
+        }
+
+    CleanupStack::PopAndDestroy(2); // buf1, writestream    
+   
+    iIncommingMessageListner.Write(0,iListenMSRPdataPckg);
+    iIncommingMessageListner.Complete(KErrNone);    
+
+    return TRUE;
+    }
+
+void CMSRPServerSubSession::ReadSendDataPckgL()
+    {
+    iClientMessage->ReadL( 0, iSendMSRPdataPckg);
+    return;
+    }
+
+TBool CMSRPServerSubSession::listnerSetupComplete()
+    {
+    if(iIncommingMessageListner.Check() && iResponseListner.Check())
+        return TRUE;
+    
+    return FALSE;        
+    }
+
+CMSRPServerSubSession::TQueueType CMSRPServerSubSession::getQToProcess()
+    {
+    // Check the pending incomming message queue and client request queue and
+    // decides which to process.
+    // The longer queue is given a priority. If queues are equal incomming message queue 
+    // is given priority.
+
+    if(iPendingSendMsgQ.Length() > iInCommingMsgQ.Length())
+        return TClientQueue;
+    else
+        return TInCommingMsgQueue;        
+    }
+
+
+TBool CMSRPServerSubSession::QueuesEmpty()
+    {
+    // Returns TRUE if there are no messages to process.
+    if(iPendingSendMsgQ.isEmpty() && iInCommingMsgQ.isEmpty())
+        return TRUE;
+    else
+        return FALSE;
+    }
+
+TBool CMSRPServerSubSession::informConnectionReadyToClient()
+    {
+    // The function informs the Client side that the pending connection request(Connect or Listen)
+    // is now complete. 
+
+    if(EDownstream == iConnDirection)
+        {
+        // Case of Connect request. 
+        iConnectionListner.Complete(KErrNone);
+        }
+    else
+        {
+        // Case of Listen.
+        iIncommingMessageListner.Complete(KErrNone);        
+        }
+    return TRUE;
+    }
+
+void CMSRPServerSubSession::QueueLog()
+    {
+    if(iOutMsgQ.Length() || iInCommingMsgQ.Length() || iPendingSendMsgQ.Length()||
+        iPendingForDeletionQ.Length())
+        {
+        // If any of the Queue is not empty. Log a event.
+        MSRPLOG2("CMSRPServerSubSession::ProcessEventL() Queue iOutMsgQ       %d",
+                    iOutMsgQ.Length());
+        
+        MSRPLOG2("CMSRPServerSubSession::ProcessEventL() Queue iInCommingMsgQ %d",
+                    iInCommingMsgQ.Length());
+        
+        MSRPLOG2("CMSRPServerSubSession::ProcessEventL() Queue iPendingSendMsgQ %d",
+                    iPendingSendMsgQ.Length());
+
+        MSRPLOG2("CMSRPServerSubSession::ProcessEventL() Queue iPendingForDeletionQ %d",
+                    iPendingForDeletionQ.Length());
+        }
+    else
+        {
+        MSRPLOG("CMSRPServerSubSession::ProcessEventL() Queue All Empty");
+        }        
+    }
+
+
+TBool CMSRPServerSubSession::checkMessageForSelfL(CMSRPMessageHandler *aMsgHandler)
+    {
+    MSRPLOG("CMSRPServerSubSession::checkMessageForSelfL");
+    CMSRPMessageBase *message = aMsgHandler->GetIncomingResponse();
+    if(!message)
+        { 
+        message = aMsgHandler->GetIncomingMessage();
+        }
+    
+    if(!message)
+        return FALSE;
+
+    // Check if the sessionID in the 'To' path matches the LocalSessionID.
+    if(FALSE == matchSessionIDL(message->ToPathHeader()))
+        return FALSE;
+
+    // Check if the sessionID in the 'From' path matches the known RemoteSessionID.
+    return matchSessionIDL(message->FromPathHeader(), FALSE);            
+    }
+
+
+TBool CMSRPServerSubSession::matchSessionIDL(const CMSRPHeaderBase *aPathHeader, TBool local)
+    {
+    TBool retVal = FALSE;
+    
+    HBufC8* textValue = aPathHeader->ToTextValueLC();        
+    TPtrC8 receivedSessionID = extractSessionID(*textValue);    
+    
+    if(local && receivedSessionID  == *iLocalSessionID)
+        retVal =  TRUE;
+
+    
+    if(!local && receivedSessionID == *iRemoteSessionID)
+        retVal =  TRUE;
+
+    CleanupStack::PopAndDestroy(textValue);
+
+    return retVal;
+    }
+
+
+TPtrC8 CMSRPServerSubSession::extractSessionID(const TDesC8& aPathBuffer)
+    {
+    // Extracts the sessionId from aPathBuffer and matches it again
+    TInt posEndOfSessionString   = 
+                aPathBuffer.LocateReverseF(KSemiColonCharacter);
+    TInt posStartOfSessionString = 
+                aPathBuffer.LocateReverseF(KDividedCharacter) + 1;
+
+    TPtrC8 receivedSessionId = aPathBuffer.Mid(posStartOfSessionString, \
+        (posEndOfSessionString - posStartOfSessionString));
+
+    return receivedSessionId;
+    }
+
+
+CStateFactory& CMSRPServerSubSession::StateFactory()
+    {
+    return iStateFactory;
+    }
+