Msrp/MsrpServer/inc/CMSRPServerSubSession.h
author Petteri Saari <petteri.saari@digia.com>
Thu, 02 Dec 2010 15:23:48 +0200
branchMSRP_FrameWork
changeset 60 7634585a4347
parent 58 cdb720e67852
permissions -rw-r--r--
This release addresses the following: - Multiple concurrent file transfer bug fixes. i.e. one device is concurrently receiving multiple files from multiple devices

/*
* 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
*
*/

#ifndef CMSRPSERVERSUBSESSION_H_
#define CMSRPSERVERSUBSESSION_H_

#include <e32std.h>
#include <e32base.h>
#include <e32math.h>
#include <in_sock.h>


#include "MMSRPConnectionObserver.h"
#include "MMSRPMessageObserver.h"
#include "MSRPServerCommon.h"
#include "CMSRPMessageHandler.h"

const TInt KMSRPSessIdLength=12;

// Forward Declarations
class CMSRPServerSubSession;
class CMSRPServerSession;
class MMSRPConnectionManager;
class CMSRPMessageBase;
class MMSRPConnection;
class MMSRPIncomingMessage;
class CMSRPMessageHandler;
class CMSRPFromToHeaderBase;
class CMSRPToPathHeader;
class CMSRPHeaderBase;

class TStateBase;
class CStateFactory;


class CRMessageContainer: public CBase
{
public:

	CRMessageContainer();
	~CRMessageContainer();
	TBool set(const RMessage2& aMessage);
	
	TInt CRMessageContainer::Write(TInt aParam,const TDesC8& aDes,TInt aOffset=0) const;
	void ReadL(TInt aParam,TDes8& aDes,TInt aOffset=0) const;

	void Complete(TInt aReason);

	TBool Check(); 	

	TBool iStatus; 
	RMessage2 iMsg;
	
};


template <class T>
class CQueue : public CBase
	{
	public:
		inline CQueue();
		virtual ~CQueue(){};
		inline TBool Queue(T& element);
		inline T* DeQueue();
		inline TBool isEmpty();
        inline T* FindElement( T* aMatch );
        inline T* FindElement( TDesC8& aMessageId );

		inline T* getHead();
		
		virtual inline T* getMatch(T* aMatch);

		TInt inline Length(){
						#ifdef _DEBUG
						if(0 == iQLenght && !iList.IsEmpty())
							{
								MSRPLOG("CQueue::Lenght!! Problem!! in the queue lenght calculations");			
							}
						#endif
						return iQLenght;
	
						};

		inline void CQueue<T>::Destroy();

	protected:
		TInt iQLenght;
	
		TSglQue<T> iList;
		
	};


template <class T>
CQueue<T>::CQueue(): iList(T::LinkOffset()),iQLenght(0){}

template <class T>
TBool CQueue<T>::Queue(T& element)
	{
	iList.AddLast(element);
	iQLenght++;
	return TRUE;
	}

template <class T>
T* CQueue<T>::DeQueue()
	{
	T* element = NULL;
	if(!(iList.IsEmpty()))
		{
		element = iList.First();
		iList.Remove(*element);
		iQLenght--;
		}

	return element;
	}

template <class T>
TBool CQueue<T>::isEmpty()
	{
		return iList.IsEmpty();
	}

template <class T>
T* CQueue<T>::getHead()
	{
		T* element = NULL;
		if(!(iList.IsEmpty()))
		{
		element = iList.First();		
		}
		return element;
	}

template <class T>
T* CQueue<T>::FindElement( T* aMatch )
    {
    if( !iList.IsEmpty() )
        {
        TSglQueIter<T> iterator(CQueue<T>::iList);
        iterator.SetToFirst();
        T* matchingOwner;
        
        while( ( matchingOwner = iterator++ ) )
            {
            if( matchingOwner == aMatch )
                {
                return matchingOwner;
                }
            }
        }
    return NULL;
    }

template <class T>
T* CQueue<T>::FindElement( TDesC8& aMessageId )
    {
    if( !iList.IsEmpty() )
        {
        TSglQueIter<T> iterator(CQueue<T>::iList);
        iterator.SetToFirst();
        T* currentElement;
        
        while( ( currentElement = iterator++ ) )
            {
            HBufC8* messageId = currentElement->MessageIdLC();
            if ( *messageId == aMessageId )
                {
                CleanupStack::PopAndDestroy( ); // messageId
                return currentElement;
                }
            CleanupStack::PopAndDestroy( ); // messageId
            }
        }
        
    return NULL;
    }

template <class T>
T* CQueue<T>::getMatch(T* aMatch)	
	{
		aMatch;
		return NULL;
	}

template<class T>
inline void CQueue<T>::Destroy()
	{
	T* element = NULL;
	TSglQueIter<T> iter(iList);
	element = iter++;
	
	while(element)
		{		
		iList.Remove(*element);
		delete element;
		element = iter++;	
		iQLenght--;
		}

	}

template<class T>
class CQueueMsgHandlers : public CQueue<T>
	{
	public:
		CQueueMsgHandlers();
		virtual ~CQueueMsgHandlers(){};
		virtual inline T* getMatch(T*);

		virtual inline TBool explicitRemove(T* aElementToRemove);		
		
	};

template<class T>
CQueueMsgHandlers<T>::CQueueMsgHandlers() : CQueue<T>::CQueue(){}

template<class T>
T*	CQueueMsgHandlers<T>::getMatch(T* aInCommingMsg)
	{
		// 

		TSglQueIter<T> iterator(CQueue<T>::iList);
		iterator.SetToFirst();
		T* iMatchingOwner;
		
		while((iMatchingOwner = iterator++))
			{
			if ( iMatchingOwner != aInCommingMsg )
			    {
                if(iMatchingOwner->IsOwnerOfResponse(*aInCommingMsg))
                    {
                    return iMatchingOwner;
                    }
                }
			}

		return NULL;
	}

template<class T>
TBool CQueueMsgHandlers<T>::explicitRemove(T* aElementToRemove)
	{
	CQueue<T>::iList.Remove(*aElementToRemove);
	CQueue<T>::iQLenght--;
		return TRUE;
		
	}

class CMSRPServerSubSession : public CBase, MMSRPConnectionObserver, MMSRPMessageObserver
    {
public:

	enum TQueueType
		{
		TClientQueue,
		TInCommingMsgQueue,
		TCompletedSendQueue,
        TCompletedIncQueue,
		TReceiveProgressQueue,
		TSendProgressQueue
		};
	
    static CMSRPServerSubSession* NewL( 
            CMSRPServerSession& aServerSession, CStateFactory& aStateFactory, const TDesC8& aSessionId );
    
    static CMSRPServerSubSession* NewLC( 
            CMSRPServerSession& aServerSession, CStateFactory& aStateFactory, const TDesC8& aSessionId );
       
    virtual ~CMSRPServerSubSession( );
       
    void ServiceL( const RMessage2& aMessage );

	// From MMSRPConnectionObserver
	void ConnectionStateL( TInt aNewState, TInt aStatus );
	
	TBool MessageReceivedL( CMSRPMessageHandler* aMsg );
	       
	void UnclaimedMessageL( CMSRPMessageHandler* aMsg );

	// From MMSRPMsgObserver
	void MessageSendCompleteL( CMSRPMessageHandler* aMessageHandler );
	
	void MessageResponseSendCompleteL(CMSRPMessageHandler& aMsg);
	
    void MessageReportSendCompleteL( CMSRPMessageHandler& aMsg );
	
	void MessageSendProgressL( CMSRPMessageHandler* aMessageHandler );
	
	void MessageReceiveProgressL( CMSRPMessageHandler* aMessageHandler );
	
	void MessageCancelledL( );
		
	void WriterError();
	
private:
    CMSRPServerSession& iServerSession;
    CMSRPServerSubSession( CMSRPServerSession& aServerSession, CStateFactory &aStateFactory);
    void ConstructL( const TDesC8& aSessionId );

	// ProcessEventL shall only take a event. The data associated with the event can be a 
	// RMessage(Client to Server events), CSendBuffer(buffer being send out by connection manager), 
	// CMSRPMessage(received message) or other such data.
	// The associated data is stored in the context and retrieved by the relevant state when needed.
	
	void CMSRPServerSubSession::ProcessEventL( TMSRPFSMEvent aEvent);
        
	//HBufC8* CreateSubSessionIDL( );
    
    void HandleLocalPathRequestL( const RMessage2& aMessage );
       
    void HandleConnectRequestL( const RMessage2& aMessage );
        
    void HandleListenConnectionsL( const RMessage2& aMessage );
    void HandleListenMessagesL( const RMessage2& aMessage );
    void HandleListenSendResultL( const RMessage2& aMessage );
       
    void HandleSendMessageL( const RMessage2& aMessage );
        
    void HandleCancelSendingL( const RMessage2& aMessage );
    void HandleCancelReceivingL( const RMessage2& aMessage );
    void HandleCancelSendRespListening( const RMessage2& aMessage );        
        
    MMSRPConnectionManager& ConnectionManager( );

	void CompleteClient(TInt aReason);
	TInt Write(TInt aParam,const TDesC8& aDes);
		
	TBool QueueClientSendRequestsL();

	TBool QueueSendMessages(CMSRPMessageHandler* aMessageHandlers);
	CMSRPMessageHandler* DeQueueSentMessage();

	TBool QueueReceivedMessages();

	// Utility functions.

	void sendResultToClientL(CMSRPMessageHandler *incommingMsgHandler);
	TBool sendMsgToClientL(CMSRPMessageHandler *incommingMsgHandler);
    TBool sendReportToClientL( CMSRPMessageHandler *incommingMsgHandler );
	void SendProgressToClientL( CMSRPMessageHandler* aMessageHandler );
	void ReceiveProgressToClientL( CMSRPMessageHandler* aMessageHandler );

	void ReadSendDataPckgL();

	TBool listnerSetupComplete();

	CMSRPServerSubSession::TQueueType getQToProcess();

	TBool QueuesEmpty();
	TBool informConnectionReadyToClient();

	void QueueLog();

    /**
    * Checks that incoming messages session id is a correct one for
    * this session
    * @param aMsgHandler message handler containing the incoming message
    * @return true if message belongs to this session, false if not
    */
    TBool CheckMessageSessionIdL( CMSRPMessageHandler *aMsgHandler );
	TBool matchSessionIDL(const CMSRPHeaderBase *aPathHeader, TBool local = TRUE);
	TPtrC8 extractSessionID(const TDesC8& aPathBuffer);

	CStateFactory& StateFactory();
        
private:
	
	// Session Data.
    HBufC8* iLocalSessionID;
    HBufC8* iRemoteSessionID;

	// Connection info bundle.        
    TBuf8< KMaxLengthOfHost > iRemoteHost;            
    TUint iRemotePort;
	TConnectionDirection  iConnDirection;

	// Local Host info
    TBuf< KMaxLengthOfHost > iLocalHost;

	MMSRPConnection* iConnection;
						    
	// connect package from the client
	TPckgBuf< TLocalPathMSRPData > iLocalPathMSRPDataPckg;
	TPckgBuf< TConnectMSRPData > iConnectMSRPdataPckg;
        
    // listen package from the client
    TPckgBuf< TListenMSRPData > iListenMSRPdataPckg;
        
    // send package to the client
    TPckgBuf< TSendMSRPData > iSendMSRPdataPckg;
        
    // result of sent messages package to the client
    TPckgBuf< TListenSendResultMSRPData > iSendResultListenMSRPDataPckg;

	// Temorary Event Data.
	const RMessage2* iClientMessage;
	CMSRPMessageHandler* iReceivedMsg;
	CMSRPMessageHandler* iReceivedResp;
    CMSRPMessageHandler* iReceivedReport;
	CMSRPMessageHandler* iReceiveFileMsgHdler;
	TBool iSendCompleteNotify; //
	TBool iReceiveCompleteNotify;
	TBool iFileShareCancelled;
	
	// used for progress reports, temporary, not owned
    CMSRPMessageHandler* iReceiveProgressMsg;
    
    // used for progress reports, temporary, not owned
    CMSRPMessageHandler* iSendProgressMsg;
	
	// Client Listners waiting to be completed.
	
	// Listner for response of Connect request.
	CRMessageContainer iConnectionListner; 
	// Listner for response of Listen request(iMessage set as false) and also 
	// listner for incomming messages(iMessage set as TRUE).
	CRMessageContainer iIncommingMessageListner;
	// Listner for Responses to sent messages.
	CRMessageContainer iResponseListner;

	CStateFactory& iStateFactory;	// Not owned.
	TStateBase* iState;				// Not owned.
	
	// The current message handler that is doing a MSRP Send and 
	// for which the subsession has still not rerceived a sendmessagecomplete event.
	// Once the sendmessage completed is received the message handler is put on the 
	// OutGoingMessage queue where it waits for a response to arrive.
	CMSRPMessageHandler *iCurrentMsgHandler;	

	// Message queues	
	CQueueMsgHandlers<CMSRPMessageHandler> iOutMsgQ;
	CQueueMsgHandlers<CMSRPMessageHandler> iInCommingMsgQ;
	CQueueMsgHandlers<CMSRPMessageHandler> iPendingSendMsgQ;
	CQueueMsgHandlers<CMSRPMessageHandler> iPendingForDeletionQ;	
    CQueueMsgHandlers< CMSRPMessageHandler > iPendingDataSendCompleteQ;    
    CQueueMsgHandlers< CMSRPMessageHandler > iPendingDataIncCompleteQ;    
    
    // progress report queues
    CQueueMsgHandlers< CMSRPMessageHandler > iPendingSendProgressQ;    
    CQueueMsgHandlers< CMSRPMessageHandler > iPendingReceiveProgressQ;    
	
	// This queue holds the instance of messages currently being received
    CQueueMsgHandlers< CMSRPMessageHandler > iCurrentlyReceivingMsgQ;    
	
	TBool iSendProgressReports;
	
	friend class TStateBase;
	friend class TStateIdle; 
	friend class TStateConnecting; 
	friend class TStateActive;
	friend class TStateWaitForClient; 
	friend class TStateError; // Not a very good thing !! Need change.

	#ifdef __UT_TSTATEFACTORY_H__
	friend class UT_TStateFactory;
	#endif

    };

#endif /* CMSRPSERVERSUBSESSION_H_ */