Msrp/MsrpServer/src/TStates.cpp
branchMSRP_FrameWork
changeset 25 505ad3f0ce5c
child 58 cdb720e67852
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Msrp/MsrpServer/src/TStates.cpp	Sat Jun 12 14:30:11 2010 +0530
@@ -0,0 +1,1147 @@
+/*
+* 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 "TStates.h"
+#include "TStateFactory.h"
+
+#include "CMSRPServerSubSession.h"
+#include "CMSRPMessageHandler.h"
+#include "CMSRPResponse.h"
+#include "MMSRPConnection.h"
+
+
+TStateBase* TStateBase::HandleStateErrorL(CMSRPServerSubSession *aContext)
+    {
+    // Error handling for invalid events received in a given state.
+    if(NULL != aContext->iClientMessage)
+        {
+        // Complete the client with a error.
+        // Set this to iClientReceivedEventData to NULL.
+        aContext->CompleteClient(KErrNone);                 
+        }
+
+    if(NULL != aContext->iReceivedMsg)
+        {
+        // !! Handle
+        }
+    return aContext->StateFactory().getStateL(EIdle);
+    }  
+
+TStateBase * TStateFileShare::processIncommingMessageL(CMSRPServerSubSession *aContext, 
+                 CMSRPMessageHandler* incommingMsg)
+    {
+    MSRPLOG("TStateFileShare::processIncommingMessage Enter!");
+    TStateBase *state = this;
+    CMSRPMessageHandler *incommingMsgHandler;
+    if(NULL != incommingMsg)
+        {
+        aContext->iInCommingMsgQ.Queue(*incommingMsg);
+        }
+    incommingMsgHandler = aContext->iInCommingMsgQ.DeQueue();         
+ 
+    while (incommingMsgHandler && state == this)
+        {
+        if(MMSRPIncomingMessage::EMSRPResponse == incommingMsgHandler->MessageType())
+            {
+            state = handlesResponseL(aContext,incommingMsgHandler);                    
+            }
+        else
+            {
+            state = handleRequestsL(aContext,incommingMsgHandler);
+            }
+        incommingMsgHandler = aContext->iInCommingMsgQ.DeQueue();
+        }
+      
+    MSRPLOG("TStateFileShare::processIncommingMessage Exit!");
+    return state;
+    }
+ 
+TStateBase* TStateBase::processIncommingMessageL(CMSRPServerSubSession *aContext, 
+                 CMSRPMessageHandler* incommingMsg)
+    {
+    MSRPLOG("TStateBase::processIncommingMessage Entered!");
+    CMSRPMessageHandler *incommingMsgHandler;
+    if(NULL == incommingMsg)
+        {
+        incommingMsgHandler = aContext->iInCommingMsgQ.DeQueue();
+        }
+    else
+        {
+        incommingMsgHandler = incommingMsg;
+        }
+ 
+    if(incommingMsgHandler)
+        {        
+        if(MMSRPIncomingMessage::EMSRPResponse == incommingMsgHandler->MessageType())
+            {
+            return handlesResponseL(aContext,incommingMsgHandler);                    
+            }
+        else
+            {
+            return handleRequestsL(aContext,incommingMsgHandler);
+            }        
+        }
+    else
+        return NULL; 
+    } 
+
+TStateBase* TStateBase::processPendingMessageQL(CMSRPServerSubSession *aContext)
+    {
+    MSRPLOG("TStateBase::processPendingMessagesL Entered!");
+    CMSRPMessageHandler *msgHandler;
+     
+    msgHandler = aContext->iPendingSendMsgQ.DeQueue();
+    msgHandler->SendMessageL(*aContext->iConnection);
+    
+    // Shift this to Outgoing Queue.
+    aContext->iCurrentMsgHandler = msgHandler;
+    return aContext->StateFactory().getStateL(EActiveSend);
+    }
+ 
+TStateBase* TStateBase::handlesResponseL(CMSRPServerSubSession *aContext,
+                 CMSRPMessageHandler *incommingMsgHandler)
+    {
+    TStateBase *nextState; 
+    MSRPLOG("TStateBase::handlesResponseL Entered!");
+    
+    // Search the outgoing Queue to find the owner of the owner of this response.
+    CMSRPMessageHandler *outgoingMsgHandler = 
+                    aContext->iOutMsgQ.getMatch(incommingMsgHandler);
+    
+    if(NULL == outgoingMsgHandler)
+        {
+        // No outgoingMsgHandler to match the received response. Stray response.
+        MSRPLOG("TStateBase::handlesResponseL() Received Stray Response!!");
+        MSRPLOG("TStateBase::handlesResponseL() No Outgoing message handler found");
+        nextState = this;
+        }
+    else
+        {
+        TBool error = 0;
+        CleanupStack::PushL(incommingMsgHandler);
+        TBool sendResult = outgoingMsgHandler->ConsumeResponseL(*incommingMsgHandler);
+         
+        if( sendResult )
+            {
+            error = aContext->sendResultToClientL(outgoingMsgHandler);
+            }        
+         
+        if(outgoingMsgHandler->IsMessageComplete())
+            {
+            aContext->iOutMsgQ.explicitRemove(outgoingMsgHandler);    
+            delete outgoingMsgHandler;
+            }
+                 
+        CleanupStack::Pop(incommingMsgHandler); 
+        if( error )
+            {
+            nextState = aContext->StateFactory().getStateL(EError);   
+            }
+        else
+            {
+            nextState = aContext->StateFactory().getStateL(EWaitForClient);     
+            }            
+        }
+    
+    delete incommingMsgHandler;    
+    
+    MSRPLOG("TStateBase::handlesResponseL Exit!");
+    return nextState;    
+    }
+ 
+TStateBase* TStateBase::handleRequestsL(CMSRPServerSubSession *aContext,
+                 CMSRPMessageHandler *incommingMsgHandler)
+    {
+    MMSRPIncomingMessage::TMSRPMessageType msgType = incommingMsgHandler->MessageType();
+    
+    if(MMSRPIncomingMessage::EMSRPMessage == msgType) // SEND request
+        {
+        MSRPLOG("SEND request received");
+        TBool sendToClient = incommingMsgHandler->SendResponseL(aContext, 
+                *aContext->iConnection, 0);        
+        if(sendToClient)
+            {
+            aContext->sendMsgToClientL(incommingMsgHandler);
+            }
+        aContext->iPendingForDeletionQ.Queue(*incommingMsgHandler);
+        return aContext->StateFactory().getStateL(EWaitForClient);
+        }
+    else if(MMSRPIncomingMessage::EMSRPReport == msgType) // Drop Reports
+        {
+        MSRPLOG("Reports not supported!!");
+        delete incommingMsgHandler;
+        return this;
+        }
+    else // It is an unrecognized request eg. AUTH
+        {
+        MSRPLOG("Unrecognized request received");
+        TBool sendToClient = incommingMsgHandler->SendResponseL(aContext, 
+                *aContext->iConnection, CMSRPResponse::EUnknownRequestMethod);        
+        aContext->iPendingForDeletionQ.Queue(*incommingMsgHandler);
+        return aContext->StateFactory().getStateL(EWaitForClient);
+        }
+    } 
+ 
+TStateBase* TStateBase::handleClientListnerCancelL(CMSRPServerSubSession * aContext, 
+        TMSRPFSMEvent aEvent)
+    {
+    if(aEvent == EMSRPCancelReceivingEvent)
+        {
+        // Confirm completion of the Cancel Request.
+        aContext->CompleteClient(KErrNone);
+        
+        // Complete the Listner if that is active.
+        if(aContext->iIncommingMessageListner.Check())
+            aContext->iIncommingMessageListner.Complete(KErrNone);
+        }    
+    
+    if(aEvent == EMSRPCancelSendRespListeningEvent)
+        {
+        // Confirm completion of the Cancel Request.
+        aContext->CompleteClient(KErrNone);
+        
+        // Complete the Listner if that is active.
+        if(aContext->iResponseListner.Check())
+            aContext->iResponseListner.Complete(KErrNone);        
+        }
+    
+    return aContext->StateFactory().getStateL(EWaitForClient);    
+    }
+  
+TStateBase* TStateBase::handleConnectionStateChangedL(CMSRPServerSubSession *aContext)
+    {
+    TStateBase* state = NULL;    
+    TInt iConnectionEvent = aContext->iConnection->getConnectionState();
+    
+    MSRPLOG2("handleConnectionStateChanged::Connection Event %d \n",iConnectionEvent ); 
+    
+    switch(iConnectionEvent)
+        {
+        case -1: // Error Scenario         
+            state = handleConnectionErrorsL(aContext);
+            break;
+        
+        case 1:
+        case 2:
+            MSRPLOG("handleConnectionStateChanged::Connection in Progress \n");
+            state = this;
+            break;
+         
+        case 3: 
+            // Connected.
+            MSRPLOG("handleConnectionStateChanged: Connected now." );    
+            aContext->informConnectionReadyToClient();
+            state = aContext->StateFactory().getStateL(EWaitForClient);            
+            break;
+        
+        case 4:
+        case 5:
+            MSRPLOG("handleConnectionStateChanged: TimeOut now." ); 
+            if(EDownstream == aContext->iConnDirection)
+                aContext->iConnectionListner.Complete(-33); // TODO : Change to query the exact erorr code from the connection.
+            else
+                aContext->iIncommingMessageListner.Complete(-33); // TODO : Change to query the exact erorr code from the connection.    
+             
+            state = aContext->StateFactory().getStateL(EWaitForClient);            
+            break;
+        
+        case 0:      
+            // Not Connected.
+            MSRPLOG("handleConnectionStateChanged: TimeOut now." );
+            state = this;  
+            break;
+        }
+    
+    return state;    
+    }
+
+TStateBase* TStateBase::handleConnectionErrorsL(CMSRPServerSubSession *aContext)
+    {
+    TStateBase* state;
+    if(TRUE == aContext->iConnectionListner.Check())
+        {
+        // Have a connection listner to inform connection errors.
+        // This scenario happens where there is a connection error during "Connect"
+        
+        aContext->iConnectionListner.Complete(KErrCouldNotConnect);  // TODO : Change to query the exact erorr code from the connection.
+        aContext->iConnection->ReleaseConnection(*aContext);
+        aContext->iConnection = NULL;
+        state = aContext->StateFactory().getStateL(EWaitForClient);        
+        }
+     else
+        {
+        // If do not have a connection listner.
+        // This is a case where a established connection(connect/listen) 
+        // is now reporting a Error.
+        
+        // ConnectionErrors in the current scheme of things will be reported via
+        // iIncommingMessageListner.
+        
+        if(!aContext->iIncommingMessageListner.Check())
+            {
+            // Case where the subsession is waiting for the Client subsessions 
+            // to provide it with listner to reports issues on.
+            // Just move to the EIdle state. EIdle is the not connected state.
+
+            // The connection error here will be reported from the TIdle state.
+            
+            state = aContext->StateFactory().getStateL(EIdle);
+            }
+        else
+            {
+            aContext->iIncommingMessageListner.Complete(KErrDisconnected);
+            aContext->iConnection->ReleaseConnection(*aContext);
+            aContext->iConnection = NULL;
+            state = aContext->StateFactory().getStateL(EIdle);
+            }
+        }
+    return state;
+    }
+
+TStateBase* TStateBase::handleQueuesL(CMSRPServerSubSession *aContext)
+    {
+    TStateBase * state;
+
+    if( aContext->QueuesEmpty() )
+        {
+        state = aContext->StateFactory().getStateL( EActive );
+        }
+    else
+        {   
+        if( CMSRPServerSubSession::TInCommingMsgQueue == 
+                           aContext->getQToProcess() )
+            state  =  processIncommingMessageL( aContext );       
+        else
+            state  =  processPendingMessageQL( aContext );
+        }   
+
+    return state;
+    }
+
+TStates TStateIdle::identity()
+    {
+    return EIdle;
+    }
+ 
+TStateBase* TStateIdle::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+    // TStateIdle is a state where the subsession is waiting to get connected.     
+    // It is the first state which is entered post sub-session creation.
+    // Also it is the state that is entered in case there is of a connection error.
+    
+    // It may be possible that the client could not be informed about the 
+    // connection error. Thus any client listner setup events will inform the client about 
+    // the current disconnected state.
+    
+    // Any existing queues of received messages, received client send requests would be 
+    // retained as it is. Any events for send messages received from the client 
+    // would be queued up.
+    
+    // An event from the connection layer is considered invalid as the connection is 
+    // assumed to be dead. Such events will result in a error report being published.
+
+     MSRPLOG2("Entered TStateIdle Event %d",aEvent);
+     TStateBase* state;
+     
+     switch(aEvent)
+         {
+         case ELocalMSRPPathEvent:
+             state =  handleLocalMSRPPathRequestL(aContext);
+             break;     
+                 
+         case EMSRPConnectEvent:  
+             aContext->iConnDirection = EDownstream; 
+             state = handleConnectRequestL(aContext);
+             break;
+             
+         case EMSRPListenEvent:        
+             aContext->iConnDirection = EUpstream;
+             state = handleListenRequestL( aContext );
+             break;         
+
+        case EMSRPListenMessagesEvent:
+        case EMSRPListenSendResultEvent:
+            // A MSRP Connection error code would be more appropriate here.
+            aContext->CompleteClient(KErrCouldNotConnect); 
+            state = this;
+            break;
+            
+        case EMSRPCancelReceivingEvent:          
+        case EMSRPCancelSendRespListeningEvent:
+             state = handleClientListnerCancelL(aContext, aEvent);
+                 break;
+
+        case EConnectionStateChangedEvent:
+             state = handleConnectionStateChangedL(aContext);
+             break;
+                 
+        default:
+             // Any such error usually a client/server protocol voilation.
+             // A bug to fix.
+             MSRPLOG2("TStateIdle::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+             state =  HandleStateErrorL(aContext);
+             break;
+        }
+    return state;     
+    }
+ 
+TStateBase* TStateIdle::handleLocalMSRPPathRequestL( CMSRPServerSubSession *aContext)
+    {
+    // The function is reponsible for contructing a  Local MSRP path and returning it to the 
+    // client.
+    // path:msrp://atlanta.example.com:7654/jshA7weztas;tcp
+    
+    // !! The current implementation should change to fully construct a MSRP path in the 
+    // subsessoin and send back the result as path buffer. Right now this done in the client. !!
+    
+    MSRPLOG("TStateIdle::HandleLocalPathRequestL()");
+     
+    TInetAddr localAddr;
+    aContext->ConnectionManager().ResolveLocalIPAddressL( localAddr );               
+    localAddr.Output(aContext->iLocalHost);          
+    
+    aContext->iLocalPathMSRPDataPckg().iLocalHost.Copy( aContext->iLocalHost );
+    aContext->iLocalPathMSRPDataPckg().iSessionID = *(aContext->iLocalSessionID);
+    
+    TInt reason = aContext->Write(0, aContext->iLocalPathMSRPDataPckg);     
+    aContext->CompleteClient(KErrNone);
+        
+    return this; // No state change.
+    }
+ 
+TStateBase* TStateIdle::handleConnectRequestL(CMSRPServerSubSession *aContext)
+    {
+    
+    if(!aContext->iConnectionListner.set(*(aContext->iClientMessage)))
+        {
+        MSRPLOG("TStateIdle::handleConnectRequestL() iConnectionListner is already setup");
+        MSRPLOG("TStateIdle::handleConnectRequestL() Invalid state to setup for ConnectionListner");
+        return HandleStateErrorL(aContext);
+        }  
+    aContext->iClientMessage = NULL; 
+    
+    aContext->iConnectionListner.ReadL( 0, aContext->iConnectMSRPdataPckg );     
+    
+    aContext->iRemoteHost = aContext->iConnectMSRPdataPckg().iRemoteHost;
+    aContext->iRemotePort = aContext->iConnectMSRPdataPckg().iRemotePort;
+    
+    aContext->iRemoteSessionID = 
+            HBufC8::NewL( aContext->iConnectMSRPdataPckg().iRemoteSessionID.Length());
+    
+    *(aContext->iRemoteSessionID) = 
+             aContext->iConnectMSRPdataPckg().iRemoteSessionID;
+    
+    // Request for a Connection.
+    MMSRPConnection &connection = 
+             aContext->ConnectionManager().getConnectionL(
+                                  aContext->iRemoteHost
+                                 ,aContext->iRemotePort);
+    aContext->iConnection = &connection;    
+    
+    TBool connReady = initializeConnectionL(aContext);
+    
+    if(!connReady)
+        { 
+        MSRPLOG("TStateIdle:: Transtion to State EConnecting" );
+        return aContext->StateFactory().getStateL(EConnecting);
+        }
+    else
+        {
+        MSRPLOG("TStateIdle:: Transtion to State EConnecting" );
+        aContext->informConnectionReadyToClient();
+        return aContext->StateFactory().getStateL(EWaitForClient);    
+        }
+    }
+ 
+TStateBase* TStateIdle::handleListenRequestL(CMSRPServerSubSession *aContext)
+    {  
+    if(!aContext->iIncommingMessageListner.set(*(aContext->iClientMessage)))
+        {
+        MSRPLOG("TStateWaitForClient::EventL iIncomming listner is already setup");
+        MSRPLOG("TStateWaitForClient::EventL Invalid state to setup a listner");
+        return HandleStateErrorL(aContext);
+        }    
+    aContext->iClientMessage = NULL;    
+    aContext->iIncommingMessageListner.ReadL( 0, aContext->iListenMSRPdataPckg );
+    
+    aContext->iRemoteHost = aContext->iListenMSRPdataPckg().iRemoteHost;
+    aContext->iRemotePort = aContext->iListenMSRPdataPckg().iRemotePort; 
+    aContext->iRemoteSessionID    = 
+            HBufC8::NewL( aContext->iListenMSRPdataPckg().iRemoteSessionID.Length());
+    
+    *(aContext->iRemoteSessionID) = 
+             aContext->iListenMSRPdataPckg().iRemoteSessionID;    
+    
+    // Request for a Connection.
+    MMSRPConnection &connection   = 
+             aContext->ConnectionManager().getConnectionL(
+                                  aContext->iRemoteHost
+                                 ,aContext->iRemotePort);
+    aContext->iConnection = &connection;    
+    
+    TBool connReady = initializeConnectionL(aContext);
+    
+    if(!connReady)
+        { 
+        MSRPLOG("TStateIdle:: Transtion to State EConnecting" );
+        return aContext->StateFactory().getStateL(EConnecting);
+        }
+    else
+        {
+        MSRPLOG("TStateIdle:: Transtion to State EConnecting" );
+        aContext->informConnectionReadyToClient();
+        return aContext->StateFactory().getStateL(EWaitForClient);    
+        }
+    } 
+ 
+TBool TStateIdle::initializeConnectionL(CMSRPServerSubSession *aContext)
+    {
+     // Connect or Listen on Connection.
+     // Return status based on connection is ready for use or not.
+    TBool retVal = FALSE;
+     
+    if(EDownstream == aContext->iConnDirection)
+        {
+        if(3 == aContext->iConnection->ConnectL(*aContext))
+            retVal = TRUE;              
+        }
+    else
+        {
+        if(3 == aContext->iConnection->ListenL(*aContext))
+            retVal = TRUE;
+        }
+     
+    return retVal;    
+    }
+ 
+TStates TStateConnecting::identity()
+    {
+    return EConnecting;
+    }
+  
+TStateBase* TStateConnecting::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+    MSRPLOG2("Entered TStateConnecting Event %d",aEvent);
+    TStateBase *state;
+
+    switch(aEvent)
+        {
+        case EConnectionStateChangedEvent:
+        state = handleConnectionStateChangedL(aContext);
+        break;
+                 
+        default:                      
+        MSRPLOG2("TStateConnecting::EventL :: Err!! Invalid state to have received %d",
+                              aEvent);                     
+        state = HandleStateErrorL(aContext);            
+        break;              
+        }
+
+    return state;    
+    }
+
+TStateBase* TStateWaitForClient::fileSendCompleteL(CMSRPServerSubSession *aContext)
+    {
+    CMSRPMessageHandler *outgoingMessageHandler = aContext->iOutMsgQ.getHead();
+    
+    if( outgoingMessageHandler  && outgoingMessageHandler->IsMessageComplete() )
+        {
+            aContext->iOutMsgQ.explicitRemove(outgoingMessageHandler);    
+             delete outgoingMessageHandler;
+             aContext->iSendCompleteNotify = TRUE;
+         }
+    return aContext->StateFactory().getStateL( EWaitForClient );   
+    }   
+
+TStateBase * TStateWaitForClient::handleResponseSentL( CMSRPServerSubSession *aContext)
+    {
+    CMSRPMessageHandler *oriMessageHandler = aContext->iReceiveFileMsgHdler;
+    oriMessageHandler->UpdateResponseStateL(aContext->iReceivedResp);
+    if(oriMessageHandler->FileTransferComplete() )
+        {
+        aContext->iReceiveCompleteNotify = TRUE;              
+        }
+    
+    return aContext->StateFactory().getStateL(EWaitForClient);    
+    }
+
+TStates TStateWaitForClient::identity()
+    {
+    return EWaitForClient;
+    }
+ 
+TStateBase* TStateBase::handleSendFileL(CMSRPServerSubSession *aContext)
+    {    
+    MSRPLOG("TStateBase::handleSendFileL() enter");
+    aContext->ReadSendDataPckgL(); 
+    CMSRPMessageHandler *aMessageHandler = CMSRPMessageHandler::NewL(aContext,
+            aContext->iSendMSRPdataPckg().iExtMessageBuffer); 
+    
+    aMessageHandler->SendFileL(*aContext->iConnection);                                        
+    
+    aContext->iOutMsgQ.Queue(*aMessageHandler);    
+    aContext->CompleteClient( KErrNone );
+    
+    aContext->iFileShare = TRUE;
+    MSRPLOG("TStateBase::handleSendFileL() exit"); 
+    if(!aContext->listnerSetupComplete())
+        {
+        return aContext->StateFactory().getStateL(EWaitForClient);
+        }
+    
+    return aContext->StateFactory().getStateL(EFileShare);
+    }
+ 
+TStateBase* TStateBase::handleReceiveFileL(CMSRPServerSubSession *aContext)
+     {     
+     MSRPLOG("TStateBase::handleReceiveFileL() enter");
+    
+     aContext->ReadSendDataPckgL(); 
+     
+     aContext->iReceiveFileMsgHdler = CMSRPMessageHandler::NewL(aContext,
+                             aContext->iSendMSRPdataPckg().iExtMessageBuffer); 
+      
+     
+     aContext->iReceiveFileMsgHdler->ReceiveFileL();
+     aContext->CompleteClient( KErrNone );
+     aContext->iFileShare = TRUE;
+     MSRPLOG("TStateBase::handleReceiveFileL() exit");
+     if(!aContext->listnerSetupComplete())
+         {
+         return aContext->StateFactory().getStateL(EWaitForClient);
+         }
+     
+     return aContext->StateFactory().getStateL(EFileShare);     
+     }
+   
+TStateBase* TStateWaitForClient::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+      // In the TStateWaitForClient stat the server subsession waits for the client to setup 
+      // handlers to receive requests/responses/reports from the MSRP peer.
+      // TODO - TStateWaitForClient can be removed. Replace this with a eventQueue implementation.
+      
+      MSRPLOG2("Entered TStateWaitForClient Event %d",aEvent);
+  
+      TStateBase *state = NULL;
+      switch(aEvent)
+          {
+          case EMSRPListenMessagesEvent:
+              if(!aContext->iIncommingMessageListner.set(*(aContext->iClientMessage)))
+                  {
+                  MSRPLOG("TStateWaitForClient::EventL iIncomming listner is already setup");
+                  MSRPLOG2("TStateWaitForClient::EventL Invalid state to have received %d", aEvent);                
+                  }              
+              aContext->iClientMessage = NULL;
+              break;
+              
+          case EMSRPListenSendResultEvent:
+              if(!aContext->iResponseListner.set(*(aContext->iClientMessage)))
+                  {
+                  MSRPLOG("TStateWaitForClient::EventL SendResult Listner is already setup");
+                  MSRPLOG2("TStateWaitForClient::EventL Invalid state to have received %d", aEvent);                
+                  }              
+              aContext->iClientMessage = NULL;
+              break;
+  
+          case EMSRPIncomingMessageReceivedEvent:
+              // Queue any thing that comes.
+              aContext->iInCommingMsgQ.Queue(*aContext->iReceivedMsg);                  
+              break;  
+              
+          case EMSRPDataSendCompleteEvent:
+              // Data Send Complete received in the TWaitForClient state is 
+              // not handeled. At Data Send Complete messae with Failure Report 
+              // header set to "no" need to inform the client about completion.
+              // Currently Queuing of completion events is not supported.
+              if(aContext->iFileShare)
+                  {
+                  state = fileSendCompleteL(aContext);
+                  break;
+                  }
+              MSRPLOG2("TStateWaitForClient::Not supported, Please check %d",aEvent);                     
+              break;
+              
+          case EMSRPResponseSendCompleteEvent:
+              if(aContext->iFileShare)
+                  {
+                  state = handleResponseSentL(aContext);  
+                  break;
+                  }
+              break;
+  
+          case EMSRPDataSendMessageEvent:
+              aContext->QueueClientSendRequestsL();                         
+              break;
+                              
+          case EMSRPCancelReceivingEvent:          
+          case EMSRPCancelSendRespListeningEvent:
+               handleClientListnerCancelL(aContext, aEvent);
+               break;
+
+          case EConnectionStateChangedEvent:
+              state = handleConnectionStateChangedL(aContext);
+              break;
+              
+          case EMSRPSendProgressEvent:
+          case EMSRPReceiveProgressEvent:
+              //ignore event if no listener
+              MSRPLOG("TStateWaitForClient::EventL Ignoring Progress Event")
+              state = aContext->StateFactory().getStateL(EWaitForClient);
+              break;
+
+          case EMSRPSendFileEvent:
+               state =  handleSendFileL(aContext);
+               break;
+               
+          case EMSRPReceiveFileEvent :
+               state =  handleReceiveFileL(aContext);
+               break;    
+                  
+          default:          
+              // Any such error usually a client/server protocol voilation or connection/subsession 
+              // protocol voilation. A bug to fix!!
+              
+              MSRPLOG2("TStateWaitForClient::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+              state = HandleStateErrorL(aContext);
+              break;              
+          };
+
+      if(NULL == state)
+        {
+          // State not set.
+          if(!aContext->listnerSetupComplete())
+              {
+              state = this;
+              }
+          else if (aContext->iFileShare)
+              {
+                  state = aContext->StateFactory().getStateL(EFileShare);
+                  
+                  if(aContext->iReceiveCompleteNotify)
+                      {
+                      aContext->NotifyFileReceiveResultToClientL(NULL);
+                      state = aContext->StateFactory().getStateL(EWaitForClient);
+                      }
+                  else if (aContext->iSendCompleteNotify)
+                      {
+                      aContext->NotifyFileSendResultToClientL(NULL);
+                      state = aContext->StateFactory().getStateL(EWaitForClient);
+                      }
+                  else if(!aContext->QueuesEmpty())
+                      state = state->handleQueuesL(aContext);                   
+              }
+          else
+            state = handleQueuesL(aContext);                  
+        }
+        return state;    
+    }
+
+TStates TStateActive::identity()
+    {
+    return EActive;
+    } 
+ 
+TStateBase* TStateActive::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+     // TStateActive is entered when the subsession is in a connected state and  client setup 
+     // is done.
+ 
+     MSRPLOG2("Entered TStateActive Event %d",aEvent);
+ 
+     TStateBase *state;
+     switch(aEvent)
+         {
+         case EMSRPDataSendMessageEvent:
+              state =  handleSendDataL(aContext);
+              break; 
+ 
+         case EMSRPIncomingMessageReceivedEvent:
+              state =  handleInCommingMessagesL(aContext);
+              break; 
+ 
+         case EMSRPSendFileEvent:
+              state =  handleSendFileL(aContext);
+              break;
+              
+         case EMSRPReceiveFileEvent :
+              state =  handleReceiveFileL(aContext);
+              break;
+             
+         case EConnectionStateChangedEvent:
+              state = handleConnectionStateChangedL(aContext);
+              break;
+  
+         case EMSRPCancelReceivingEvent:          
+         case EMSRPCancelSendRespListeningEvent:
+              state =  handleClientListnerCancelL(aContext, aEvent);
+              break;             
+ 
+         default: 
+             // Any such error usually a client/server protocol voilation or connection/subsession 
+             // protocol voilation. A bug to fix!!
+             
+             MSRPLOG2("TStateActive::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+             state =  HandleStateErrorL(aContext); 
+             break; 
+         }
+
+     return state;     
+    } 
+ 
+TStateBase* TStateActive::handleSendDataL(CMSRPServerSubSession *aContext)
+    {
+    MSRPLOG("TStateActive::handleSendDataL()");     
+    
+    aContext->ReadSendDataPckgL(); 
+    
+    CMSRPMessageHandler *msgHandler 
+     = CMSRPMessageHandler::NewL(aContext,
+         aContext->iSendMSRPdataPckg().iExtMessageBuffer); 
+    
+    msgHandler->SendMessageL( *aContext->iConnection );                    
+    aContext->iCurrentMsgHandler = msgHandler;
+    
+    aContext->CompleteClient( KErrNone );
+    
+    return aContext->StateFactory().getStateL(EActiveSend);
+    }
+   
+TStateBase* TStateBase::handleInCommingMessagesL(CMSRPServerSubSession *aContext)
+     {
+     CMSRPMessageHandler* incommingMsg = aContext->iReceivedMsg;
+     aContext->iReceivedMsg = NULL;
+     
+     return processIncommingMessageL(aContext, incommingMsg);             
+     }
+ 
+TStates TStateFileShare::identity()
+     {
+     return EFileShare;
+     } 
+ 
+TStateBase* TStateFileShare::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+     {
+     TStateBase *state = NULL;
+     MSRPLOG2("Entered TStateFileShare Event %d",aEvent);
+     switch(aEvent)
+         {
+         case EMSRPDataSendCompleteEvent: // maps to file send complete
+              state = fileSendCompleteL(aContext);
+              break;
+             
+         case EMSRPIncomingMessageReceivedEvent:  // incoming responses to file chunks
+             state =  handleInCommingMessagesL(aContext);
+              break;
+              
+         case EMSRPResponseSendCompleteEvent:
+             state = handleResponseSentL(aContext);  
+              break;
+         
+         case EMSRPSendProgressEvent:
+             state = handleSendProgressL(aContext);
+             break;
+             
+         case EMSRPReceiveProgressEvent:
+             state = handleReceiveProgressL(aContext);             
+             break;
+                  
+         case EConnectionStateChangedEvent :
+             state = handleConnectionStateChangedL(aContext); 
+             break;
+
+              
+         case EMSRPCancelReceivingEvent:
+         case EMSRPCancelSendRespListeningEvent:
+              state =  handleClientListnerCancelL(aContext, aEvent);
+              break;  
+         default:
+               MSRPLOG2("TStateFileShare::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+              // state =  HandleStateErrorL(aContext);      //handle error state       
+               break;
+         
+         }
+         return state;
+     }
+ 
+TStateBase * TStateFileShare::handleSendProgressL( CMSRPServerSubSession *aContext)
+     {
+     CMSRPMessageHandler *outgoingMessageHandler = aContext->iOutMsgQ.getHead();
+     aContext->SendProgressToClientL(outgoingMessageHandler);
+     return aContext->StateFactory().getStateL( EWaitForClient ); 
+     }
+ 
+TStateBase * TStateFileShare::handleReceiveProgressL( CMSRPServerSubSession *aContext)
+     {
+     CMSRPMessageHandler *oriMessageHandler = aContext->iReceiveFileMsgHdler;     
+     aContext->ReceiveProgressToClientL(oriMessageHandler);
+     return aContext->StateFactory().getStateL( EWaitForClient );
+     }
+ 
+TStateBase * TStateFileShare::handleResponseSentL( CMSRPServerSubSession *aContext)
+     {
+     CMSRPMessageHandler *oriMessageHandler = aContext->iReceiveFileMsgHdler;
+     oriMessageHandler->UpdateResponseStateL(aContext->iReceivedResp);
+     
+
+      if(oriMessageHandler->FileTransferComplete() )
+         {
+         //Notify client
+         aContext->NotifyFileReceiveResultToClientL(oriMessageHandler);
+         delete oriMessageHandler;
+         aContext->iReceiveFileMsgHdler = NULL;
+         return aContext->StateFactory().getStateL(EWaitForClient);
+         }
+     
+     if(!aContext->listnerSetupComplete())
+         {
+         return aContext->StateFactory().getStateL(EWaitForClient);
+         }
+     
+     return aContext->StateFactory().getStateL(EFileShare);
+     
+     }
+  
+TStateBase * TStateFileShare::handlesResponseL(CMSRPServerSubSession *aContext,
+                  CMSRPMessageHandler *incommingMsgHandler)
+      {
+      TStateBase *nextState; 
+      MSRPLOG("TStateFileShare::handlesFileResponseL Entered!");
+      
+      // Search the outgoing Queue to find the owner of  this response.
+      CMSRPMessageHandler *outgoingMsgHandler = 
+                         aContext->iOutMsgQ.getMatch(incommingMsgHandler);
+
+      nextState = this;
+      if(NULL != outgoingMsgHandler)
+         {
+         CleanupStack::PushL(incommingMsgHandler);
+         outgoingMsgHandler->ConsumeFileResponseL(*incommingMsgHandler);
+        
+         if(outgoingMsgHandler->FileTransferComplete())    
+            {
+             //notify client
+            aContext->NotifyFileSendResultToClientL(outgoingMsgHandler);
+            aContext->iOutMsgQ.explicitRemove(outgoingMsgHandler);    
+            delete outgoingMsgHandler;        
+            nextState = aContext->StateFactory().getStateL(EWaitForClient);
+            }    
+        
+         CleanupStack::Pop(incommingMsgHandler);
+         }
+      delete incommingMsgHandler;
+      MSRPLOG("TStateFileShare::handlesResponseL Exit!");
+      if(!aContext->listnerSetupComplete())
+          {
+          return aContext->StateFactory().getStateL(EWaitForClient);
+          }
+      return nextState; 
+      }
+  
+TStateBase * TStateFileShare::handleRequestsL(CMSRPServerSubSession *aContext,
+                 CMSRPMessageHandler *incommingMsgHandler)
+     {     
+     if(MMSRPIncomingMessage::EMSRPMessage == incommingMsgHandler->MessageType())
+         {
+         CMSRPMessageHandler *oriMessageHandler = aContext->iReceiveFileMsgHdler;
+         
+         if(oriMessageHandler->IsInFile())
+             {   
+             oriMessageHandler->WritetoFileL(incommingMsgHandler);
+             incommingMsgHandler->SendResponseL(aContext, *aContext->iConnection,CMSRPResponse::EAllOk);
+             if(!incommingMsgHandler->IfResponseReqL())
+                 {
+                 delete incommingMsgHandler;
+                 if(oriMessageHandler->FileTransferComplete())
+                     {
+                     aContext->NotifyFileReceiveResultToClientL(oriMessageHandler);
+                     delete oriMessageHandler;
+         	         aContext->iReceiveFileMsgHdler = NULL;
+                     return aContext->StateFactory().getStateL(EWaitForClient);   
+                     }
+                 }
+           
+             else
+                 {
+                 aContext->iPendingForDeletionQ.Queue(*incommingMsgHandler);
+                 }              
+              }
+          }
+     else
+         {
+         MSRPLOG("Reports not supported.!!");
+         delete incommingMsgHandler;         
+         }
+     if(!aContext->listnerSetupComplete())
+         {
+         return aContext->StateFactory().getStateL(EWaitForClient);
+         }
+     return this; 
+     }
+ 
+TStateBase* TStateFileShare::fileSendCompleteL(CMSRPServerSubSession *aContext)
+     {
+     CMSRPMessageHandler *outgoingMessageHandler = aContext->iOutMsgQ.getHead();
+     
+     if( outgoingMessageHandler  && outgoingMessageHandler->IsMessageComplete() )
+         {
+             //notify client
+              aContext->NotifyFileSendResultToClientL( outgoingMessageHandler );
+              aContext->iOutMsgQ.explicitRemove(outgoingMessageHandler);    
+              delete outgoingMessageHandler;
+              return aContext->StateFactory().getStateL( EWaitForClient ); 
+          }
+         // response needed keep it on the outmsg queue itself
+     return aContext->StateFactory().getStateL( EFileShare );   
+     }   
+ 
+TStates TStateActiveSend::identity()
+    {
+    return EActiveSend;
+    }
+ 
+TStateBase* TStateActiveSend::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+     // ActiveSend state. The subsession is busy sending earlier data. Any further requests to 
+     // send data from the client will be queued. Any Message received will be queued till 
+     // EMSRPDataSendCompleteEvent is received. 
+     // After this Message Received Queue will be processed to check for any 
+     // incoming messages/responses.
+     // After that Message send queue will be processed to see if there any pending messages to 
+     // trasmitt.
+     // If both the queues are empty move back to Active State.
+
+     TStateBase *state;
+     MSRPLOG2("Entered TStateActiveSend Event %d",aEvent); 
+ 
+     switch(aEvent)
+         {
+         case EMSRPDataSendMessageEvent:
+             aContext->QueueClientSendRequestsL();
+             state = this;          
+             break;
+     
+         case EMSRPDataSendCompleteEvent:
+             state = MessageSendCompleteL(aContext);
+             break;
+ 
+         case EMSRPIncomingMessageReceivedEvent:
+             // Queue any thing that comes.
+             aContext->iInCommingMsgQ.Queue(*aContext->iReceivedMsg);
+             state = this;           
+             break;
+
+         case EConnectionStateChangedEvent:
+              state = handleConnectionStateChangedL(aContext);
+              break;
+              
+         case EMSRPCancelReceivingEvent:          
+         case EMSRPCancelSendRespListeningEvent:
+             state =  handleClientListnerCancelL(aContext, aEvent);
+             break;              
+ 
+         default: 
+             // Any such error usually a client/server protocol voilation or connection/subsession 
+             // protocol voilation. A bug to fix!!
+             
+             MSRPLOG2("TStateActiveSend::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+             state =  HandleStateErrorL(aContext);            
+             break; 
+         } 
+     return state;
+    }
+ 
+TStateBase * TStateActiveSend::MessageSendCompleteL(CMSRPServerSubSession *aContext)
+    {
+    // Handle send message complete event.
+    if( NULL == aContext->iCurrentMsgHandler)
+        {
+        MSRPLOG( "TStateActiveSend::MessageSendCompleteL :: iCurrentMsgHandler is NULL \n" );                                     
+        return this;
+        }
+        
+    if( aContext->iCurrentMsgHandler->IsMessageComplete() )
+        {
+        // Messages with Failure Report set to "No" will never get a response.        
+        TBool error = aContext->sendResultToClientL( aContext->iCurrentMsgHandler );        
+        delete aContext->iCurrentMsgHandler;
+        aContext->iCurrentMsgHandler = NULL;
+        
+        return aContext->StateFactory().getStateL( EWaitForClient );
+        }
+    else
+        {
+        // Message expects a response to come. Put this out the OutGoing Queue.
+        aContext->iOutMsgQ.Queue( *(aContext->iCurrentMsgHandler) );
+        aContext->iCurrentMsgHandler = NULL;
+        
+        // Handle any pending events in Queue.
+        return handleQueuesL(aContext);     
+        }
+    } 
+
+
+TStates TStateError::identity()
+    {
+    return EError;
+    } 
+
+TStateBase* TStateError::EventL(TMSRPFSMEvent aEvent, CMSRPServerSubSession *aContext)
+    {
+    // Error State is entered when we receive an Error Response from the opposite
+    // end point to which we sent a SEND request. When this state is entered the client
+    // is expected to close the session without trying to send further messages.
+    
+    MSRPLOG2("Entered TStateError Event %d", aEvent);
+    TStateBase *state;
+    
+    switch(aEvent)
+        {
+        case EMSRPListenMessagesEvent:
+            aContext->CompleteClient(KErrCouldNotConnect); 
+            state = this;
+            break;
+            
+        case EMSRPListenSendResultEvent:
+            aContext->CompleteClient(EInvalidAction); 
+            state = this;
+            break;
+            
+        case EMSRPDataSendMessageEvent:
+            aContext->CompleteClient(KErrNone); 
+            state = this;
+            break;
+            
+        case EMSRPCancelReceivingEvent:
+        case EMSRPCancelSendRespListeningEvent:
+            state = handleClientListnerCancelL(aContext, aEvent);
+            break;
+            
+        case EMSRPIncomingMessageReceivedEvent:            
+            aContext->iInCommingMsgQ.Queue(*aContext->iReceivedMsg);
+            state = this;           
+            break;
+        
+        case EConnectionStateChangedEvent:
+            state = handleConnectionStateChangedL(aContext);
+            break;
+            
+        default:
+            MSRPLOG2("TStateError::EventL :: Err!! Invalid state to have received %d",aEvent);                     
+            state =  HandleStateErrorL(aContext);            
+            break;                  
+        }    
+    return state;   
+    }