// -----------------------------------------------------------------------------
// CSIPExSIPIdleState::InviteReceivedL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPIdleState::InviteReceivedL( 
    CSIPExSIPEngine& aEngine,
	CSIPServerTransaction* aTransaction )
	{
	_LIT8( KLogEntry, "180 Ringing sent" );

	// Get dialog association, save for future use
	CSIPInviteDialogAssoc* dialogAssoc =
		CSIPInviteDialogAssoc::NewL( *aTransaction );
	aEngine.SetDialogAssoc( *dialogAssoc );
    
	// Create the necessary response elements and send
    CSIPResponseElements* elem =
    	CSIPResponseElements::NewLC( 
    	    180, SIPStrings::StringF( SipStrConsts::EPhraseRinging ) );
    aTransaction->SendResponseL( elem );
    CleanupStack::Pop( elem );
	aEngine.Observer()->WriteLog( KLogEntry );

	// Get the From header from the request
	const CSIPRequestElements* reqElem = aTransaction->RequestElements();
	const CSIPFromHeader* fromHeader = reqElem->FromHeader();
	
	// Change machine state
	aEngine.SetCurrentState( iServerOfferingState );

    TUint32 iapId( 0 );
	User::LeaveIfError( 
	        aEngine.Profile().GetParameter( KSIPAccessPointId, iapId ) );
	
	// Send user name from the From header to the Engine Observer 
	// as a parameter. Send also id of used IAP.
	aEngine.Observer()->InviteReceived( 
	    fromHeader->SIPAddress().Uri8().Uri().Extract( EUriUserinfo ), iapId );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPServerOfferingState::CancelReceivedL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPServerOfferingState::CancelReceivedL(
	CSIPExSIPEngine& aEngine,
	CSIPClientTransaction& /*aTransaction */ )
	{
	aEngine.Observer()->SessionEnded();
	aEngine.SetCurrentState( iTerminatedState );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPServerOfferingState::AcceptInviteL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPServerOfferingState::AcceptInviteL( CSIPExSIPEngine& aEngine)
	{
	_LIT8( KMediaType, "application" );
	_LIT8( KMediaSubType, "sdp" );
	_LIT8( KLogEntry, "200 OK sent" );

	// Get the current transaction
	CSIPServerTransaction& tx = aEngine.ServerTx();
	// Create the Response Elements object
    CSIPResponseElements* respElem =
    	CSIPResponseElements::NewLC( 
    	    200, SIPStrings::StringF( SipStrConsts::EPhraseOk ) );
    
    // Set the message body - we need to communicate our IP Address
    CSIPMessageElements& msgElem = respElem->MessageElements();

	CSdpDocument* sdpDocument = aEngine.SdpDocumentLC();
	HBufC8* sdpBody = aEngine.SdpBodyL( sdpDocument );
	CleanupStack::PushL( sdpBody );

   	CSIPContentTypeHeader* ct =
   		CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
	msgElem.SetContentL( sdpBody, ct );

	// Use the transaction to send 200 (OK)
	tx.SendResponseL( respElem );

	CleanupStack::Pop( ct );
	CleanupStack::Pop( sdpBody );
	CleanupStack::PopAndDestroy( sdpDocument );
	CleanupStack::Pop( respElem );

	aEngine.SetCurrentState( iServerEstablishingState );
	aEngine.Observer()->WriteLog( KLogEntry );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPClientEstablishingState::CancelInviteL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPClientEstablishingState::CancelInviteL( CSIPExSIPEngine& aEngine )
	{
	// Get the current Client Transaction
	CSIPClientTransaction& clientTA = aEngine.ClientTx();

	// Use it the to send CANCEL request
    CSIPClientTransaction* ta = clientTA.CancelL();
    delete ta;

	aEngine.SetCurrentState( iIdleState );
	aEngine.Observer()->InvitationCancelled();
	}
// -----------------------------------------------------------------------------
// CSIPExSIPServerOfferingState::DeclineInviteL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPServerOfferingState::DeclineInviteL( CSIPExSIPEngine& aEngine )
	{
	// Get the current transaction
	CSIPServerTransaction& tx = aEngine.ServerTx();
	// Create the Response Elements object
    CSIPResponseElements* elem =
    	CSIPResponseElements::NewLC( 486, 
    	    SIPStrings::StringF( SipStrConsts::EPhraseBusyHere ) );

	// Use the transaction to send 486 (Busy Here)
	tx.SendResponseL( elem );

	CleanupStack::Pop( elem );
	aEngine.Observer()->SessionEnded();
	aEngine.SetCurrentState( iTerminatedState );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPServerOfferingState::ByeReceivedL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPServerOfferingState::ByeReceivedL(
	CSIPExSIPEngine& aEngine,
	CSIPServerTransaction& aTransaction )
	{
	// Create and send response
    CSIPResponseElements* elem = 
        CSIPResponseElements::NewLC( 
            200, SIPStrings::StringF( SipStrConsts::EPhraseOk ) );
    aTransaction.SendResponseL( elem );
    CleanupStack::Pop( elem );

	// Inform observer
	aEngine.Observer()->SessionEnded();
	
	// Set state
	aEngine.SetCurrentState( iTerminatedState );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPTerminatingState::ResponseReceivedL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPTerminatingState::ResponseReceivedL(
	CSIPExSIPEngine& aEngine,
	CSIPClientTransaction& aTransaction )
	{
	const CSIPResponseElements* respElem = aTransaction.ResponseElements();

	if ( respElem->StatusCode() == 200 )
		{
		aEngine.Observer()->SessionEnded();
		aEngine.ClearClientTx();
		aEngine.SetCurrentState( iIdleState );
		}
	else
		{
		// Hmmm...
		}
	}
// -----------------------------------------------------------------------------
// CSIPExSIPIdleState::SendInviteL()
// Create and send an INVITE request to the recipient.
// -----------------------------------------------------------------------------
void CSIPExSIPIdleState::SendInviteL( 
    CSIPExSIPEngine& aEngine,
	const TDesC8& aSipUri )
	{
	// Retrieve the active profile and connection
	CSIPProfile& prof = aEngine.Profile();
	CSIPConnection& conn = aEngine.ConnectionL();

    // Create CUri8 from passed descriptor
    CUri8* uri8 = aEngine.ConvertToUri8LC( aSipUri );
    
	// Get dialog association, save for future use
	// The ownership of uri8 is transferred
	CSIPInviteDialogAssoc* dialogAssoc =
		CSIPInviteDialogAssoc::NewL( conn, uri8, prof );
	CleanupStack::Pop( uri8 );	
		
	aEngine.SetDialogAssoc( *dialogAssoc ); //Ownership is transferred!!

	// Create the necessary message elements
	CSIPMessageElements* msgElements = aEngine.CreateMessageElementsLC();

	// Send the INVITE in the dialog
	// The ownership of msgElements is transferred
	CSIPClientTransaction* tx = dialogAssoc->SendInviteL( msgElements );
	CleanupStack::Pop( msgElements );

	// Save the pointer to the transaction to the Engine
	aEngine.SetClientTx( tx );

	// Change machine state
	aEngine.SetCurrentState( iClientEstablishingState );
	}
// -----------------------------------------------------------------------------
// CSIPExSIPClientEstablishingState::ResponseReceivedL()
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CSIPExSIPClientEstablishingState::ResponseReceivedL(
	CSIPExSIPEngine& aEngine,
	CSIPClientTransaction& aTransaction )
	{
	const CSIPResponseElements* respElem = aTransaction.ResponseElements();

	TUint statusCode = respElem->StatusCode();

	if ( statusCode >= 200 && statusCode < 300 )
		{
		// Final Response received from network.
		// Get the IP Address of the remote party from the Response Elements
		const TInetAddr addr = 
		            aEngine.IPAddressFromResponseElementsL( *respElem );
		
		// Get used iap's id
		TUint32 iapId( 0 );
		CSIPConnection* conn = aEngine.DialogAssoc().Dialog().Connection();
		if ( conn )
		    {
		    iapId = conn->IapId();
		    }

		// Then, send ACK to remote party
		CSIPInviteDialogAssoc& dialogAssoc = aEngine.DialogAssoc();
		dialogAssoc.SendAckL( aTransaction );


		// After ACKing, notify observer, giving IP Address and IAP id
		// as parameter
		aEngine.Observer()->InviteAcceptedByRemote( addr, iapId );


		// Finally, change engine state
		aEngine.SetCurrentState( iEstablishedState );
		}
	else if ( statusCode >= 100 && statusCode < 200 )
		{
		// Provisional Response received from network.
		aEngine.Observer()->InviteReceivedByRemote( statusCode );
		aEngine.SetCurrentState( iClientOfferingState );
		}
	else
		{
		aEngine.Observer()->InviteDeclinedByRemote( statusCode );
		aEngine.SetCurrentState( iIdleState );
		}
	}