multimediacommsengine/mmcesrv/mmceserver/src/mcesipevent.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcesipevent.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1283 @@
+/*
+* Copyright (c) 2005 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:  
+*
+*/
+
+
+
+
+#include <sipmessageelements.h>
+#include <sipnotifydialogassoc.h>
+#include <siprefertoheader.h>
+#include <sipreferdialogassoc.h>
+#include <sipsubscribedialogassoc.h>
+#include <sipsubscriptionstateheader.h>
+#include <siptoheader.h>
+#include <sipexpiresheader.h>
+#include <sipeventheader.h>
+#include <siprequestelements.h>
+#include <sipservertransaction.h>
+#include <sipprofile.h>
+#include <sipdialog.h>
+#include <siptransactionbase.h>
+#include <sipdialogassocbase.h>
+#include "mcesip.h"
+
+#include "mceevent.h"
+#include "mcerefer.h"
+
+#include "mcesipevent.h"
+#include "mcesipconnection.h"
+#include "mceserial.h"
+#include "mceevents.h"
+#include "mceclientserver.h"
+#include "mcesrvlogs.h"
+#include "mcecomevent.h"
+#include "mcesipeventhelper.h"
+
+#include "mcecssessionreceiver.h"
+#include "mcecssubsessionreceiver.h"
+#include "mcecssession.h"
+#include "mcecssessionimplementation.h"
+#include "mcecomevent.h"
+#include "mcesipmanager.h"
+#include "mcesipconnection.h"
+
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::NewL
+// -----------------------------------------------------------------------------
+//
+CMceSipEvent* CMceSipEvent::NewL( CMceCsSession& aClientSession, 
+								  CMceSipConnection& aSIPConnection,
+								  CSIPProfile& aProfile)
+	{
+    CMceSipEvent* self = CMceSipEvent::NewLC( aClientSession, 
+    										  aSIPConnection, 
+    										  aProfile );
+    CleanupStack::Pop(self);
+    return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::NewLC
+// -----------------------------------------------------------------------------
+//
+CMceSipEvent* CMceSipEvent::NewLC ( CMceCsSession& aClientSession, 
+									CMceSipConnection& aSIPConnection,
+									CSIPProfile& aProfile)
+	{
+    CMceSipEvent* self = 
+        new (ELeave) CMceSipEvent( aClientSession, aSIPConnection, aProfile );
+    CleanupStack::PushL(self);
+    self->ConstructL( aClientSession );
+    return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CMceSipEvent
+// -----------------------------------------------------------------------------
+//
+CMceSipEvent::CMceSipEvent ( CMceCsSession& aClientSession, 
+							 CMceSipConnection& aSIPConnection,
+							 CSIPProfile& aProfile )
+: CMceCsSubSession( KMceCSSIPEvent, aClientSession, aSIPConnection, aProfile )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::ConstructL ( CMceCsSession& aClientSession )
+	{
+	CMceCsSubSession::ConstructL( aClientSession );
+			
+    MCESRV_DEBUG("MCE SIP event created") 	
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::~CMceSipEvent
+// -----------------------------------------------------------------------------
+//
+CMceSipEvent::~CMceSipEvent()
+	{
+    MCESRV_DEBUG("MCE SIP event deleted") ;	
+    if(iEvent)
+    	{
+   		 delete iEvent; 		
+    	}
+    if ( iIdle )
+        {
+        delete iIdle;    
+        }
+    }
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CanDispose
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipEvent::CanDispose()
+    {
+    return !iEvent || 
+        iEvent->EventContext().CurrentState() == KMceTerminatedEventStateIndex;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::HandleSIPEvent
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::HandleSIPEvent( TMceSipEventCode /*aEventCode*/ )
+    {
+    TRAPD( error, iEvent->ProceedL() );
+    if ( error )
+        {
+        ErrorOccured(error);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::ResponseReceived()
+    {
+    HandleSIPEvent( EMceResponse );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ProvisionalResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::ProvisionalResponseReceived()
+    {
+    HandleSIPEvent( EMceProvisionalResponse );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::RedirectionResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::RedirectionResponseReceived()
+    {
+    HandleSIPEvent( EMceRedirectionResponse );
+    }
+ 
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ErrorResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::ErrorResponseReceived()
+    {
+    HandleSIPEvent( EMceErrorResponse );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::RequestReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::RequestReceived( TBool /*aInsideDialog*/, CSIPDialog& /*aDialog*/ )
+    {
+    
+    MCESRV_DEBUG( "CMceSipEvent::RequestReceived -- begin" )            				
+   	TInt error=KErrNone;
+    RStringF method = MceSip::Method( Request() );
+    
+    if ( AcceptMethod( method ) && iEvent )
+        {         
+    	MCESRV_DEBUG( "CMceSipEvent::RequestReceived -- passing to event" )
+        TRAP ( error, iEvent->ReceivedRequestL() );	
+        MCESRV_DEBUG( "CMceSipEvent::RequestReceived -- handled" )
+        }
+    else
+        {
+        error = KErrGeneral;
+        }
+    
+    if ( error != KErrNone )
+        {
+        MceSip::DiscardRequest( Request() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::StandAloneRequestReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::StandAloneRequestReceived()
+    {
+    MCESRV_DEBUG("CMceSipEvent::StandAloneRequestReceived, Entry");
+    MceSip::DiscardRequest( Request() );
+    MCESRV_DEBUG("CMceSipEvent::StandAloneRequestReceived, Exit");
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::StandAloneResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::StandAloneResponseReceived( TMceSipResponseType /*aResponseType*/ )
+    {
+    MCESRV_DEBUG("CMceSipEvent::StandAloneResponseReceived, Entry");
+    // NOP
+    MCESRV_DEBUG("CMceSipEvent::StandAloneResponseReceived, Exit");
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::ErrorOccured( TInt aError )
+    {
+    TMceIds ids;
+    ids.iCallbackID = EMceItcStateChanged;
+    ids.iState = CMceEvent::ETerminated;
+    
+    SendErrorToClient( ids, aError );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::DoErrorOccured( TInt aError, 
+                                   CSIPTransactionBase& /*aTransaction*/ )
+    {
+    ErrorOccured( aError );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoConnectionStateChanged
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::DoConnectionStateChanged( TBool aIsActive )
+    {
+    if ( iEvent && !aIsActive )
+        {
+        TRAP_IGNORE( iEvent->PerformActionL( EMceItcTerminateEvent ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::Canceled
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::Canceled()
+    {
+    if ( ClientType() == KMceDlgTypeRefer )
+        {
+        TRAP_IGNORE( ClientStateChangedL( CMceRefer::ETerminated, EFalse ) );
+        }
+    else
+        {
+        TRAP_IGNORE( ClientStateChangedL( CMceEvent::ETerminated, EFalse ) );
+        }
+    
+    MCE_DELETE( iEvent );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::Terminate
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipEvent::Terminate()
+    {
+    return CanDispose();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoServiceL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceSipEvent::DoServiceL( TMceIds& aIds, 
+               TMceItcFunctions aFunction )
+    {
+    MCESRV_DEBUG( "CMceSipEvent::DoServiceL(ids), Entry" );
+    
+    LocalDoServiceL( aIds, aFunction );
+        
+    MCESRV_DEBUG( "CMceSipEvent::DoServiceL(ids), Exit" );
+    
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::DoServiceL( TMceIds& /*aIds*/, 
+               TMceItcFunctions /*aFunction*/, 
+ 	           const TDesC8& /*aMessage*/ )
+    {
+    MCESRV_DEBUG( "CMceSipEvent::DoServiceL(str), Entry" );
+    
+    User::Leave( KErrNotSupported );
+    MCESRV_DEBUG( "CMceSipEvent::DoServiceL(str), Exit" );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::DoServiceL( TMceIds& aIds, 
+                               TMceItcFunctions aFunction, 
+							   CMceMsgBase& aMessage ) 
+    {
+    MCESRV_DEBUG( "CMceSipEvent::DoServiceL(message), Entry" );
+    
+    if ( !iEvent )
+        {
+        User::LeaveIfError( aMessage.Type() == EMceItcMsgTypeEvent ? 
+            KErrNone : KErrNotSupported );
+        CMceMsgSIPEvent* eventMsg = 
+        	    static_cast< CMceMsgSIPEvent* >( &aMessage );
+        DoInitializeL( aFunction, *eventMsg );
+        }
+    
+    CMceMsgSIPData* dataMsg = static_cast< CMceMsgSIPData* >( &aMessage );
+    UpdateDataL( aFunction, *dataMsg );
+    
+    LocalDoServiceL( aIds, aFunction, *dataMsg );
+    
+    ClearDataL();
+    MCESRV_DEBUG( "CMceSipEvent::ServiceL(message), Exit" );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoInitializeIncomingDialogL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::DoInitializeIncomingDialogL( 
+                                        CSIPServerTransaction& aTransaction )
+    {
+    User::LeaveIfError( Dialog() ? KErrNone : KErrTotalLossOfPrecision );
+    User::LeaveIfError( 
+        Dialog()->Type() == SIPStrings::StringF( SipStrConsts::ENotify ) ?
+        KErrNone : KErrNotSupported );
+        
+    if( aTransaction.Type() == 
+        SIPStrings::StringF( SipStrConsts::ESubscribe ) )
+    	{
+    	SetEventStateType( EMtSubscribe );		
+    	}
+    else
+    	{
+    	SetEventStateType( EMtRefer );		
+    	}
+    	
+    const CSIPNotifyDialogAssoc* notify = 
+        static_cast< CSIPNotifyDialogAssoc* >( Dialog() );
+    
+    iEvent = CMceComEvent::NewL( 
+                            *this,
+                		    notify->SubscriptionState().ExpiresParameter() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::IncomingSubscribeL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::IncomingSubscribeL(CDesC8Array* aHeaders,
+                    				  HBufC8* aContentType,
+									  HBufC8* aBody)
+	{
+	// get ID of SIP profile this SUBSCRIBE was received to.
+	TUint32 matchId;
+    User::LeaveIfError( Profile().GetParameter( KSIPProfileId, matchId ) );
+    
+	 // Copy input parameters to avoid ownership transfer problem if leave occurs
+    CDesC8Array* tempHeaders = CopyArrayLC( aHeaders ); 
+    HBufC8* tempContentType = CopyBufferLC( aContentType );
+	
+    // make and encode message for ITC
+    HBufC8* empty = KMceEmpty().AllocLC();
+	HBufC8* recipient = Dialog()->Dialog().ToHeader().ToTextValueLC();
+	HBufC8* originator = Dialog()->Dialog().FromHeader().ToTextValueLC();
+	HBufC8* eventHeader = 
+	    ( ( CSIPNotifyDialogAssoc* ) Dialog() )->Event().ToTextValueLC();
+	TUint32 id = reinterpret_cast<TUint32>(this);
+	CMceMsgSIPEvent* eventMsg = 
+        new (ELeave) CMceMsgSIPEvent( id,
+                                      DialogId(),
+                                      EMceItcEventTypeSubscribe,
+                                      recipient, // recipient
+                                      originator, // originator
+                                      eventHeader, // event header 
+                                      empty, // refer to
+                                      CMceRefer::ENoSuppression, // suppress
+                                      ( TUint )KErrNotFound, // interval
+                                      tempHeaders, 
+                                      tempContentType );
+    
+    CleanupStack::Pop( eventHeader );
+    CleanupStack::Pop( originator );
+    CleanupStack::Pop( recipient );
+    CleanupStack::Pop( empty );
+	if ( tempContentType )
+        {
+        CleanupStack::Pop( tempContentType );
+        }
+    if ( tempHeaders )
+        {
+        CleanupStack::Pop( tempHeaders );
+        }
+
+    CleanupStack::PushL( eventMsg );                                
+    eventMsg->EncodeL();
+	HBufC8* encMsg = eventMsg->EncodeBufferCloneL();
+	CleanupStack::PopAndDestroy( eventMsg );
+	CleanupStack::PushL( encMsg );
+    	
+    TMceIds ids;
+    ids.iManagerType = KMceCSSIPEvent;
+    ids.iProfileID = matchId;
+    ids.iCallbackID = EMceItcObjectAdded;
+	ids.iState = CMceEvent::EIdle;
+	ids.iMsgType = EMceItcMsgTypeEvent;
+	
+    // send	
+    Client().SendToClientL( ids, encMsg, aBody );
+
+	CleanupStack::Pop( encMsg );
+
+	delete aHeaders;
+	delete aContentType;
+    }
+					
+// -----------------------------------------------------------------------------
+// CMceSipEvent::IncomingReferL
+// -----------------------------------------------------------------------------
+//									
+void CMceSipEvent::IncomingReferL(HBufC8* aReferTo,
+					CDesC8Array* aHeaders,
+                    HBufC8* aContentType,
+					HBufC8* aBody )
+	{
+	MCESRV_DEBUG( "CMceSipEvent::IncomingReferL -- Begin" );
+	// get ID of SIP profile this REFER was received to.
+	TUint32 matchId;
+    User::LeaveIfError( Profile().GetParameter( KSIPProfileId, matchId ) );
+	
+    // Copy input parameters to avoid ownership transfer problem if leave occurs
+    HBufC8* tempReferTo = CopyBufferLC( aReferTo );
+    CDesC8Array* tempHeaders = CopyArrayLC( aHeaders ); 
+    HBufC8* tempContentType = CopyBufferLC( aContentType );
+
+	// make and encode message for ITC
+	HBufC8* recipient = Dialog()->Dialog().ToHeader().ToTextValueLC();
+	HBufC8* originator = Dialog()->Dialog().FromHeader().ToTextValueLC();
+	HBufC8* eventHeader = 
+	    ( ( CSIPNotifyDialogAssoc* ) Dialog() )->Event().ToTextValueLC();
+	
+	
+	TUint32 id = reinterpret_cast<TUint32>(this);
+	
+	CMceMsgSIPEvent* eventMsg = 
+        new (ELeave) CMceMsgSIPEvent( id,
+                                      DialogId(),
+                                      EMceItcEventTypeRefer,
+                                      recipient, // recipient
+                                      originator, // originator
+                                      eventHeader, // event header
+                                      tempReferTo, 
+                                      iEvent->ReferType(),
+                                      ( TUint32 )KErrNotFound, // interval
+                                      tempHeaders, 
+                                      tempContentType );
+    
+    CleanupStack::Pop( eventHeader );
+    CleanupStack::Pop( originator );
+    CleanupStack::Pop( recipient );
+    if ( tempContentType )
+        {
+        CleanupStack::Pop( tempContentType );
+        }
+    if ( tempHeaders )
+        {
+        CleanupStack::Pop( tempHeaders );
+        }
+    if ( tempReferTo )
+        {
+        CleanupStack::Pop( tempReferTo );
+        }
+
+    CleanupStack::PushL( eventMsg );
+    eventMsg->EncodeL();
+	HBufC8* encMsg = eventMsg->EncodeBufferCloneL();
+	CleanupStack::PopAndDestroy( eventMsg ); 
+	CleanupStack::PushL( encMsg );
+	
+    // send	
+    TMceIds ids;
+    ids.iManagerType = KMceCSSIPEvent;
+    ids.iProfileID = matchId;
+    ids.iCallbackID = EMceItcObjectAdded;
+	ids.iState = CMceRefer::EIdle;
+	ids.iMsgType = EMceItcMsgTypeEvent;
+	
+    Client().SendToClientL( ids, encMsg, aBody );
+
+	CleanupStack::Pop( encMsg );
+
+	delete aHeaders;
+	delete aContentType;
+	delete aReferTo;
+
+    MCESRV_DEBUG( "Incoming REFER sent to client" );
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ClientStateChangedL
+// -----------------------------------------------------------------------------
+//									
+void CMceSipEvent::ClientStateChangedL( CMceRefer::TState aState, 
+                                        TBool aIsResponse )
+    {
+    DoClientStateChangedL( aState, aIsResponse );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ClientStateChangedL
+// -----------------------------------------------------------------------------
+//									
+void CMceSipEvent::ClientStateChangedL( CMceEvent::TState aState, 
+                                        TBool aIsResponse )
+	{
+	DoClientStateChangedL( aState, aIsResponse );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoClientStateChangedL
+// -----------------------------------------------------------------------------
+//									
+void CMceSipEvent::DoClientStateChangedL( TUint32 aState, TBool aIsResponse )
+	{
+	MCESRV_DEBUG_DVALUE( "Event state changed. new state", aState );
+	
+    // update IDs
+	TMceIds ids;
+    ids.iState = aState;
+    ids.iCallbackID = EMceItcStateChanged;
+    ids.iMsgType = EMceItcMsgTypeSIPReply;
+    
+    if ( aIsResponse )
+        {
+        const CSIPResponseElements* response = Response().ResponseElements();
+        RStringF reasonPhrase = response->ReasonPhrase();
+	    TUint statusCode = response->StatusCode();
+		CDesC8ArrayFlat* headers = new (ELeave) CDesC8ArrayFlat(1);		
+	    CleanupStack::PushL( headers );
+	    
+		const RPointerArray<CSIPHeaderBase>& sipHeaders = 
+		    response->MessageElements().UserHeaders();
+		
+		for (int i=0; i < sipHeaders.Count(); i++)
+			{
+			CSIPHeaderBase* anotherhead = sipHeaders[i];
+			HBufC8* head = anotherhead->ToTextLC();
+			headers->AppendL(*head);
+			CleanupStack::PopAndDestroy( head );
+			}    
+
+	    HBufC8* reason = reasonPhrase.DesC().AllocLC();
+		HBufC8* empty = KMceEmpty().AllocLC();    
+
+    	CMceMsgSIPReply* replyMsg = new (ELeave) CMceMsgSIPReply( 
+    	    *reason, 
+    	    statusCode, 
+    	    *headers, 
+    	    *empty );
+    	CleanupStack::PushL( replyMsg );
+    	replyMsg->EncodeL();
+    	
+		HBufC8* context = replyMsg->EncodeBufferCloneL();
+	    CleanupStack::PopAndDestroy( replyMsg );
+	    
+    	CleanupStack::PushL( context );
+		HBufC8* content = response->MessageElements().Content().AllocLC();
+		
+	    SendToClientL( ids, context, content );
+    
+	    CleanupStack::Pop( content);
+	    CleanupStack::Pop( context);
+    	CleanupStack::PopAndDestroy( empty );
+    	CleanupStack::PopAndDestroy( reason );
+    	CleanupStack::PopAndDestroy( headers );  
+	    }
+    else
+    	{
+	    SendToClient( ids );
+    	}
+    MCESRV_DEBUG( "New event state sent to client" );
+    }		
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::NotifyReceived
+// -----------------------------------------------------------------------------
+//				
+void CMceSipEvent::NotifyReceivedL(CDesC8Array* aHeaders,
+                    				HBufC8* aContentType,
+									HBufC8* aBody )
+	{	
+    // update IDs
+    TMceIds ids;
+    ids.iCallbackID = EMceItcNotifyReceived;
+    ids.iMsgType = EMceItcMsgTypeEvent;
+    ids.iState = CMceEvent::EActive;
+
+	// Copy input parameters to avoid ownership transfer problem if leave occurs
+    CDesC8Array* tempHeaders = CopyArrayLC( aHeaders ); 
+    HBufC8* tempContentType = CopyBufferLC( aContentType );
+
+    // make and encode message for ITC
+    HBufC8* recipient = Dialog()->Dialog().ToHeader().ToTextValueLC();
+	HBufC8* originator = Dialog()->Dialog().FromHeader().ToTextValueLC();
+	HBufC8* emptyEvent = KMceEmpty().AllocLC();
+	HBufC8* emptyReferTo = KMceEmpty().AllocLC();
+	
+	CMceMsgSIPEvent* eventMsg = 
+        new (ELeave) CMceMsgSIPEvent( ids.iSessionID,
+                                      DialogId(),
+                                      EMceItcEventTypeEither,
+                                      recipient, // recipient
+                                      originator, // originator
+                                      emptyEvent, // event header 
+                                      emptyReferTo, // referTo
+                                      CMceRefer::ENoSuppression, // suppress
+                                      ( TUint )KErrNotFound, // interval
+                                      tempHeaders, 
+                                      tempContentType );
+    CleanupStack::Pop( emptyReferTo );                                  
+    CleanupStack::Pop( emptyEvent );
+    CleanupStack::Pop( originator );
+    CleanupStack::Pop( recipient );
+    if ( tempContentType )
+        {
+        CleanupStack::Pop( tempContentType );
+        }
+    if ( tempHeaders )
+        {
+        CleanupStack::Pop( tempHeaders );
+        }
+
+    CleanupStack::PushL( eventMsg );
+    eventMsg->EncodeL();
+	HBufC8* encMsg = eventMsg->EncodeBufferCloneL();
+	CleanupStack::PopAndDestroy( eventMsg );
+	CleanupStack::PushL( encMsg );
+	
+	// send
+    SendToClientL( ids, encMsg, aBody );
+    
+    CleanupStack::Pop( encMsg );
+    
+    delete aHeaders;
+    delete aContentType;
+    }
+	
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CreateIncomingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipEvent::CreateIncomingDialogL( 
+                                          CSIPServerTransaction& aTransaction )
+    {
+    User::LeaveIfError( 
+        aTransaction.Type() == SIPStrings::StringF( SipStrConsts::ERefer ) || 
+        aTransaction.Type() == SIPStrings::StringF( SipStrConsts::ESubscribe ) ? 
+        KErrNone : KErrNotSupported );
+    
+    User::LeaveIfError( 
+        aTransaction.RequestElements() ? KErrNone : KErrArgument );
+        
+    const CSIPMessageElements& message = 
+        aTransaction.RequestElements()->MessageElements();
+    
+    // get expires header value, if exists.
+    CSIPHeaderBase* expiresHeaderTmp = MceSip::FindHeader( message,
+        SIPStrings::StringF(SipStrConsts::EExpiresHeader ) );	
+        
+    TUint expires = KMceDefaultSubscrExpire;
+    if ( expiresHeaderTmp )
+        {
+        CSIPExpiresHeader* expiresHeader = 
+        static_cast< CSIPExpiresHeader* >( expiresHeaderTmp );
+        expires = expiresHeader->Value();    
+        }
+        
+        // get event header from the server transaction
+    CSIPHeaderBase* eventHeaderTmp = MceSip::FindHeader( message,
+        SIPStrings::StringF( SipStrConsts::EEventHeader ) );
+        
+    CSIPEventHeader* eventHeader = NULL;
+    if ( eventHeaderTmp )
+        {
+        // use event from request, if present
+        eventHeader =   
+            static_cast< CSIPEventHeader* >( eventHeaderTmp->CloneL() );
+        }
+    else if ( aTransaction.Type() == 
+        SIPStrings::StringF(SipStrConsts::ERefer ) )
+        {
+        // For REFER, Event is "refer"
+        eventHeader = CSIPEventHeader::NewL( KMceSipEventPackageRefer );
+        }
+    else
+        {
+        // SUBSCRIBE with no Event header
+        User::Leave( KErrNotSupported );
+        }
+    CleanupStack::PushL( eventHeader );
+    
+    // create subscription state header
+    CSIPSubscriptionStateHeader* subscrStateHeader = NULL;
+    if ( expires > 0 )
+        {
+        subscrStateHeader = 
+            CSIPSubscriptionStateHeader::NewLC( KStateActive );
+        }
+    else
+        {
+        subscrStateHeader = 
+            CSIPSubscriptionStateHeader::NewLC( KStateTerminated );
+        }
+    subscrStateHeader->SetExpiresParameterL( expires );
+    // create notify dialog assoc.
+    const MSIPRegistrationContext& profile = Profile();    
+    CSIPNotifyDialogAssoc* dialog = CSIPNotifyDialogAssoc::NewL( 
+                                                        aTransaction, 
+                                                        profile,
+                                                        eventHeader, 
+                                                        subscrStateHeader );
+    CleanupStack::Pop( subscrStateHeader );
+    CleanupStack::Pop( eventHeader );
+    return dialog;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipEvent::CreateOutgoingDialogL( 
+                                                TMceDialogType aDialogType, 
+                                                CDesC8Array& aParams,
+                                                CSIPDialog& aExistingDialog )
+                                                          
+    {
+    User::LeaveIfError( aDialogType == KMceDlgTypeRefer ||
+                     aDialogType == KMceDlgTypeSubscribe ?
+                     KErrNone : KErrArgument );
+                            
+    CSIPDialogAssocBase* dialog = NULL;
+    
+    if ( aDialogType == KMceDlgTypeSubscribe )
+        {
+        TPtrC8 eventHeader = aParams.MdcaPoint( KMceArrayIndexEventHeader );
+        
+        CSIPEventHeader* sipEventHeader = 
+            CSIPEventHeader::DecodeL( eventHeader );
+        CleanupStack::PushL( sipEventHeader );
+    
+        dialog = CSIPSubscribeDialogAssoc::NewL( aExistingDialog, 
+                                                 sipEventHeader );         
+    
+        CleanupStack::Pop( sipEventHeader );
+        }
+    else
+        {
+        TPtrC8 referTo = aParams.MdcaPoint( KMceArrayIndexEventReferTo );
+            
+        CSIPReferToHeader* referToHeader = 
+            CSIPReferToHeader::DecodeL( referTo ); 
+        CleanupStack::PushL( referToHeader );
+        dialog = CSIPReferDialogAssoc::NewL( aExistingDialog,
+                                             referToHeader );
+                                             
+        CleanupStack::Pop( referToHeader );
+        
+        }
+        
+        
+    return dialog;
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipEvent::CreateOutgoingDialogL( 
+                                                    TMceDialogType aDialogType,
+                                                    CDesC8Array& aParams )
+    {
+    User::LeaveIfError( aDialogType == KMceDlgTypeRefer ||
+                        aDialogType == KMceDlgTypeSubscribe ?
+                        KErrNone : KErrArgument );
+                            
+    CSIPDialogAssocBase* dialog = NULL;
+    
+    CSIPConnection& connection = SIPConnection().Connection();
+    const CSIPProfile& profile = Profile();
+    TPtrC8 eventRemoteUri = aParams.MdcaPoint( KMceArrayIndexEventRemoteURI );
+    TPtrC8 originator = aParams.MdcaPoint( KMceArrayIndexEventOriginator );
+    CSIPToHeader* toHeader = CSIPToHeader::DecodeL( eventRemoteUri );
+    CleanupStack::PushL( toHeader );
+	CUri8* remoteUri = CUri8::NewLC( toHeader->SIPAddress().Uri8().Uri() );
+	
+	CSIPFromHeader* fromHeader = NULL;
+    if ( originator.Length() > 0 )
+        {
+        fromHeader = MceSip::ToFromHeaderL( originator );
+        }
+    CleanupStack::PushL( fromHeader );
+        
+    if ( aDialogType == KMceDlgTypeSubscribe )
+        {
+        TPtrC8 eventHeader = aParams.MdcaPoint( KMceArrayIndexEventHeader );
+        
+        CSIPEventHeader* sipEventHeader = 
+            CSIPEventHeader::DecodeL( eventHeader );
+        CleanupStack::PushL( sipEventHeader );
+    
+        dialog = CSIPSubscribeDialogAssoc::NewL( connection,
+                                                 remoteUri,
+                                                 profile,
+                                                 sipEventHeader,
+                                                 fromHeader,
+                                                 toHeader );         
+    
+        CleanupStack::Pop( sipEventHeader );
+        }
+    else
+        {
+        TPtrC8 referTo = aParams.MdcaPoint( KMceArrayIndexEventReferTo );
+            
+        CSIPReferToHeader* referToHeader = 
+            CSIPReferToHeader::DecodeL( referTo ); 
+        CleanupStack::PushL( referToHeader );
+        dialog = CSIPReferDialogAssoc::NewL( connection,
+                                             remoteUri,
+                                             profile,
+                                             referToHeader,
+                                             fromHeader,
+                                             toHeader );
+                                             
+        CleanupStack::Pop( referToHeader );
+        
+        }
+    CleanupStack::Pop( fromHeader );
+    CleanupStack::Pop( remoteUri );
+    CleanupStack::Pop( toHeader );
+        
+    return dialog;
+    
+    }
+		
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::AcceptDialogTransaction
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipEvent::AcceptDialogTransaction( 
+    CSIPServerTransaction& aTransaction )
+    {
+    TBool ret = EFalse;
+    TRAP_IGNORE((ret = AcceptDialogTransactionL (aTransaction ) ));
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::AcceptDialogTransactionL
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipEvent::AcceptDialogTransactionL( 
+                                    CSIPServerTransaction& aTransaction )
+    {
+    TBool ret = EFalse;
+    User::LeaveIfError( Dialog() ? KErrNone : KErrArgument );
+    User::LeaveIfError( iEvent ? KErrNone : KErrTotalLossOfPrecision );
+    User::LeaveIfError( 
+        aTransaction.RequestElements() ? KErrNone : KErrArgument );
+        
+    CSIPHeaderBase* head = 
+      MceSip::FindHeader( aTransaction.RequestElements()->MessageElements(),
+                          SIPStrings::StringF( SipStrConsts::EEventHeader ) );
+    User::LeaveIfError( head ? KErrNone : KErrArgument );
+    
+    const RStringF tranType = aTransaction.Type();
+    const RStringF dlgType = Dialog()->Type();
+            
+    CSIPEventHeader* tranEventHeader = static_cast<CSIPEventHeader*>( head );
+    if ( tranType == SIPStrings::StringF( SipStrConsts::ESubscribe ) )
+        {
+        // We have MT SUBSCRIBE or MT REFER
+        // The event package and the id must match to 
+        // the one of the NOTIFY dialog assoc.
+        if ( dlgType == SIPStrings::StringF( SipStrConsts::ENotify ) )
+            {
+            // match to NOTIFY dialog event header
+            ret = MCESIPEventHelper::MatchEvents( 
+                static_cast< CSIPNotifyDialogAssoc* >( Dialog() )->Event(), 
+                *tranEventHeader );
+            }
+        }
+    else if ( tranType == SIPStrings::StringF( SipStrConsts::ENotify ) )
+        {
+        // We have MO SUBSCRIBE or MO REFER
+        if ( iStateType == EMoSubscribe )
+            {
+            if ( dlgType == SIPStrings::StringF( SipStrConsts::ESubscribe ) )
+                {
+                // The event package and id must match to the
+                // one of the subscribe dialog assoc.
+                ret = MCESIPEventHelper::MatchEvents( 
+                                static_cast< CSIPSubscribeDialogAssoc* >
+                                    ( Dialog() )->Event(),
+                                *tranEventHeader );
+                }
+            }
+        else if ( iStateType == EMoRefer )
+            {
+            // The event package must be "refer" and the
+            // id is either not present or must mach to the
+            // CSeq number of the sent REFER.
+            ret = MCESIPEventHelper::MatchEventsL( KMceSipEventPackageRefer,
+                                                  iEvent->IdValue(),
+                                                  *tranEventHeader );
+            }
+        }
+    return ret;        
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::AcceptMethod
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipEvent::AcceptMethod( RStringF aMethod )
+    {
+    
+    return aMethod == SIPStrings::StringF(SipStrConsts::ERefer ) || 
+           aMethod == SIPStrings::StringF(SipStrConsts::ESubscribe)||
+           aMethod == SIPStrings::StringF(SipStrConsts::ENotify );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::SetEventStateType
+// -----------------------------------------------------------------------------
+// 
+void CMceSipEvent::SetEventStateType(const TEventStateType aEventStateType )
+	{
+	iStateType = aEventStateType;	
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::EventStateType
+// -----------------------------------------------------------------------------
+// 	
+TEventStateType CMceSipEvent::EventStateType() const
+	{
+	return iStateType;	
+	}
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::ClearDataL
+// -----------------------------------------------------------------------------
+// 	
+void CMceSipEvent::ClearDataL()
+    {
+    iEvent->SetMsgHeaders( NULL );    
+    iEvent->SetMsgContentL( NULL, NULL );
+    iEvent->SetReasonPhraseL( ( TUint32 ) KErrNotFound, NULL );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoInitializeL
+// -----------------------------------------------------------------------------
+// 	    
+void CMceSipEvent::DoInitializeL( TMceItcFunctions aFunction, 
+                                  CMceMsgSIPEvent& aMessage )
+    {
+    switch( aFunction )
+        {
+        case EMceItcSubscribe:
+            {
+        	//Create MO Subscribe event
+			SetEventStateType( EMoSubscribe );
+            break;
+            }
+        case EMceItcReferEvent:
+            {
+            //Create MO Refer event
+            SetEventStateType( EMoRefer );
+            break;
+            }
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+    iEvent = CMceComEvent::NewL( *this, aMessage.RefreshInterval() );
+    iEvent->SetReferType( 
+        static_cast< CMceRefer::TType >( aMessage.ReferType() ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::LocalDoServiceL( TMceIds& aIds, 
+                               TMceItcFunctions aFunction, 
+                               CMceMsgSIPData& aMessage )
+    {
+    MCESRV_DEBUG( "CMceSipEvent::LocalDoServiceL( message ), Entry" );
+    switch( aFunction )
+        {
+        case EMceItcRespondEvent:
+            {
+            CMceMsgSIPReply* replyMsg = 
+                static_cast< CMceMsgSIPReply* >( &aMessage );
+            TBool terminated = 
+                ( replyMsg->iCode >= KMceSipMultipleChoices ? ETrue : EFalse );
+            
+            if ( iEvent->ReferType() != CMceRefer::ENoSuppression )
+                {
+                if ( terminated )
+        	        {
+        	        aIds.iState = CMceRefer::ETerminated;
+        	        }
+        	    else if ( replyMsg->iCode >= KMceSipOK )
+        	        {
+        	        aIds.iState = CMceRefer::EAccepted;
+                    //Asynchronically put the event in terminated state
+                    User::LeaveIfError( !iIdle ? 
+                        KErrNone : KErrTotalLossOfPrecision );
+                    iIdle = CIdle::NewL( CActive::EPriorityIdle );
+                    iIdle ->Start( TCallBack( Idle, this ) );
+        	        }
+        	    else
+        	        {
+        	        // provisional
+        	        // NOP
+        	        }
+                }
+            else // not suppressed
+                {
+                aIds.iState = ( terminated ? 
+                    CMceEvent::ETerminated : CMceEvent::EPending );
+                }
+            break;
+            }
+        default :
+            {
+            // NOP 
+            break;
+            }
+        }
+        
+    LocalDoServiceL( aIds, aFunction );
+    
+    MCESRV_DEBUG( "CMceSipEvent::LocalDoServiceL( message ), Exit" );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::LocalDoServiceL( TMceIds& aIds, TMceItcFunctions aFunction )
+    {
+    MCESRV_DEBUG( "CMceSipEvent::LocalDoServiceL, Entry" );
+    User::LeaveIfError( iEvent ? KErrNone : KErrTotalLossOfPrecision );
+    // call state machine
+    iEvent->PerformActionL( aFunction );	
+    
+    // update ids and other actions, if needed.
+    switch ( aFunction )
+        {
+        case EMceItcSubscribe:
+        case EMceItcSubscribeUpdate:
+        case EMceItcTerminateEvent:
+            {
+            aIds.iState = CMceEvent::EPending;
+            break;
+            }
+        case EMceItcReferEvent:
+        case EMceItcNotify:
+            {
+            aIds.iState = ( iEvent->ReferType() != CMceRefer::ENoSuppression ?  
+                CMceRefer::EPending : CMceEvent::EPending );
+            break;
+            }
+        case EMceItcRespondEvent:
+            {
+            // NOP
+            break;
+            }
+        case EMceItcAcceptEvent:
+            { 
+            if ( iEvent->ReferType() != CMceRefer::ENoSuppression )
+                {
+                aIds.iState = CMceRefer::EAccepted;
+                //Asynchronically put the event in terminated state
+                User::LeaveIfError( !iIdle ? 
+                    KErrNone : KErrTotalLossOfPrecision );
+                iIdle = CIdle::NewL( CActive::EPriorityIdle );
+                iIdle ->Start( TCallBack( Idle, this ) );
+                }
+            else
+                {
+                aIds.iState = CMceEvent::EPending;
+                }
+            break;
+            }
+        case EMceItcRejectEvent:
+    		{
+    		aIds.iState = ( iEvent->ReferType() != CMceRefer::ENoSuppression ?  
+                CMceRefer::ETerminated : CMceEvent::ETerminated );
+            break;	
+    		}
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+            
+    MCESRV_DEBUG( "CMceSipEvent::LocalDoServiceL, Exit" );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::UpdateDataL
+// -----------------------------------------------------------------------------
+//
+void CMceSipEvent::UpdateDataL( TMceItcFunctions aFunction, 
+                                CMceMsgSIPData& aMessage )
+    {
+    MCESRV_DEBUG( "CMceSipEvent::UpdateDataL, Entry" );
+        
+    switch( aFunction )
+        {
+        case EMceItcSubscribe:
+        case EMceItcNotify:
+        case EMceItcReferEvent:
+        case EMceItcTerminateEvent://only in MT
+            {
+            User::LeaveIfError ( aMessage.Type() == EMceItcMsgTypeEvent ?
+                KErrNone : KErrNotSupported );
+            						
+        	break;
+            }
+        case EMceItcSubscribeUpdate:
+            {
+            User::LeaveIfError ( aMessage.Type() == EMceItcMsgTypeEvent ?
+                KErrNone : KErrNotSupported );
+            
+            CMceMsgSIPEvent* eventMsg = 
+                static_cast< CMceMsgSIPEvent* >( &aMessage );
+            
+            iEvent->SetRefreshInterval( eventMsg->RefreshInterval() );
+            break;
+            }
+      case EMceItcRespondEvent:
+        	{
+        	User::LeaveIfError ( aMessage.Type() == EMceItcMsgTypeSIPReply ?
+                KErrNone : KErrNotSupported );
+            
+        	CMceMsgSIPReply* replyMsg = 
+        	    static_cast< CMceMsgSIPReply* >( &aMessage );
+        	HBufC8* reason = replyMsg->Reason();
+        	CleanupStack::PushL( reason );
+            iEvent->SetReasonPhraseL( replyMsg->iCode, reason );
+        	CleanupStack::Pop( reason );
+            break;	
+        	}
+      default:
+            {
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+        
+    iEvent->SetMsgHeaders( aMessage.Headers() );
+    
+    HBufC8* content = PopClientContent();
+    CleanupStack::PushL( content );
+    HBufC8* contentType = aMessage.ContentType();
+    CleanupStack::PushL( contentType );
+    
+    iEvent->SetMsgContentL( contentType, content );
+    CleanupStack::Pop( contentType );
+    CleanupStack::Pop( content );
+    
+    
+    MCESRV_DEBUG( "CMceSipEvent::UpdateDataL, Exit" );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::SuppressedReferTerminated
+// -----------------------------------------------------------------------------
+// 	
+void CMceSipEvent::SuppressedReferTerminated()
+    {
+    delete iIdle;
+    iIdle = NULL;
+    TRAP_IGNORE( ClientStateChangedL( CMceRefer::ETerminated, EFalse ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::Idle
+// -----------------------------------------------------------------------------
+// 	
+TInt CMceSipEvent::Idle( TAny* aObject )
+    {
+    CMceSipEvent* event = reinterpret_cast< CMceSipEvent* >( aObject );
+    event->SuppressedReferTerminated();
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CopyArrayLC
+// -----------------------------------------------------------------------------
+// 
+CDesC8Array* CMceSipEvent::CopyArrayLC( const CDesC8Array* aArray )
+    {
+    CDesC8Array* tempArray = NULL;
+    if ( aArray )
+        {
+        tempArray = new ( ELeave ) CDesC8ArrayFlat( KMceArrayGranularity );
+        CleanupStack::PushL( tempArray );
+        for ( TInt i = 0; i < aArray->MdcaCount(); i++ )
+            {
+            tempArray->AppendL( aArray->MdcaPoint( i ) );
+            }
+        }
+    return tempArray;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipEvent::CopyBufferLC
+// -----------------------------------------------------------------------------
+// 
+HBufC8* CMceSipEvent::CopyBufferLC( const HBufC8* aBuffer )
+    {
+    HBufC8* tempBuffer = NULL;
+    if ( aBuffer )
+        {
+        tempBuffer = aBuffer->AllocLC();
+        }
+    return tempBuffer;
+    }
+    
+//  End of File