realtimenetprots/sipfw/SampleApp/sipengine/src/SIPExSIPEngine.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SampleApp/sipengine/src/SIPExSIPEngine.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1213 @@
+
+// Copyright (c) 2004-2009 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 FILES
+//
+
+
+
+#include "SIPExSIPEngine.h"
+#include "SIPExSIPStateBase.h"
+
+#include <uri8.h>
+#include <sipstrings.h>
+#include <sipstrconsts.h>
+
+// CONSTANTS
+
+_LIT8( KSdpNoInfoDesC8, "-" );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+EXPORT_C CSIPExSIPEngine* CSIPExSIPEngine::NewL( 
+    TUid aAppUid,
+	MSIPExSIPEngineObserver* aObserver )
+	{
+	CSIPExSIPEngine* self = new( ELeave ) CSIPExSIPEngine();
+	CleanupStack::PushL( self );
+	self->ConstructL( aAppUid, aObserver );
+	CleanupStack::Pop( self );
+	
+	return self;
+	}
+
+
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+CSIPExSIPEngine::~CSIPExSIPEngine()
+	{
+	SdpCodecStringPool::Close();
+	
+	delete iIdle;
+	delete iClientEstablishing;
+	delete iClientOffering;
+	delete iServerOffering;
+	delete iServerEstablishing;
+	delete iEstablished;
+	delete iTerminating;
+
+	delete iClientTx;
+	delete iServerTx;
+
+	delete iDialogAssoc;
+
+	delete iConnection;
+	delete iProfile;
+	delete iProfileRegistry;
+	delete iSIP;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CSIPExSIPEngine
+// C++ default constructor.
+// -----------------------------------------------------------------------------
+CSIPExSIPEngine::CSIPExSIPEngine()
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ConstructL
+// Symbian 2nd phase constructor. Can leave.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ConstructL( 
+    TUid aAppUid,
+	MSIPExSIPEngineObserver* aObserver )
+	{
+	// Make note of the observer class.
+	iObserver = aObserver;
+
+	// Create instances of the CSIP and Profile Registry classes
+	iSIP = CSIP::NewL( aAppUid, *this );
+	iProfileRegistry = CSIPProfileRegistry::NewL( *iSIP, *this );
+
+	// Open SDP Codec String Pool
+	StringPoolL();
+
+	// Set our local address
+	const TUint32 KInetAddr = INET_ADDR(127,0,0,1);
+	iLocalAddr.SetAddress( KInetAddr );
+
+	// Set up the state machine
+	// Create instances of the state classes.
+	iIdle = CSIPExSIPIdleState::NewL();
+	iClientEstablishing = CSIPExSIPClientEstablishingState::NewL();
+	iClientOffering = CSIPExSIPClientOfferingState::NewL();
+	iServerOffering = CSIPExSIPServerOfferingState::NewL();
+	iServerEstablishing = CSIPExSIPServerEstablishingState::NewL();
+	iEstablished = CSIPExSIPEstablishedState::NewL();
+	iTerminating = CSIPExSIPTerminatingState::NewL();
+
+	// Create the links for state transitions.
+	iIdle->LinkStates( *iClientEstablishing, *iServerOffering );
+	iClientEstablishing->LinkStates( *iIdle, *iClientOffering, *iEstablished );
+	iClientOffering->LinkStates( *iIdle, *iEstablished, *iIdle );
+	iServerOffering->LinkStates( *iServerEstablishing, *iIdle );
+	iServerEstablishing->LinkStates( *iEstablished, *iIdle );
+	iEstablished->LinkStates( *iTerminating, *iIdle );
+	iTerminating->LinkStates( *iIdle );
+
+	// Set current state data
+	iCurrentState = iIdle;
+	iConnState = CSIPConnection::EInactive;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::EnableProfileL
+// First get the default profile from the registry, then, if it is
+// an IETF profile, enable it.
+// If non-IETF profile is default, call error callback with KErrNotSupported
+// and leave
+// Not part of the state machine.
+// -----------------------------------------------------------------------------
+EXPORT_C TBool CSIPExSIPEngine::EnableProfileL()
+	{
+	// Check for existing profile
+	if ( iProfile )
+		{
+		delete iProfile;
+		iProfile = NULL;
+		}
+    TBool registered( EFalse );
+    
+    // Leaves with KErrNotFound if default profile is not found
+	iProfile = iProfileRegistry->DefaultProfileL();
+
+    // Safety check that DefaultProfile() didn't return NULL pointer.
+    if ( !iProfile )
+        {
+        iObserver->ProfileError( KErrNotFound );
+        _LIT8( KProfileError, "Profile not found. Define a profile:");
+        iObserver->WriteLog(KProfileError());
+		User::Leave( KErrNotFound );
+        }
+    // Leaves if profile type is not EInternet
+    else if ( iProfile->Type().iSIPProfileClass != TSIPProfileTypeInfo::EInternet )
+		{
+		delete iProfile;
+		iProfile = NULL;
+		iObserver->ProfileError( KErrNotSupported );
+		User::Leave( KErrNotSupported );
+		}
+	else
+		{
+		const TDesC8* aor = NULL;
+    	iProfile->GetParameter( KSIPUserAor, aor );  	
+    	iObserver->WriteLog( *aor );
+		iProfileRegistry->EnableL( *iProfile, *this );
+		
+		// check whether profile was immediately set to registered state
+		iProfile->GetParameter( KSIPProfileRegistered, registered );
+		}
+		
+    return registered;
+	}
+		
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::DisableProfileL
+// Disable the profile given as a parameter.
+// Not part of the state machine.
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::DisableProfileL()
+	{
+	if ( iProfile )
+		{
+		iProfileRegistry->Disable( *iProfile );
+		delete iProfile;
+		iProfile = NULL;		
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SendInviteL
+// Send INVITE to the remote peer given as a parameter.
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::SendInviteL( const TDesC8& aSipUri )
+	{
+	iCurrentState->SendInviteL( *this, aSipUri );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CancelInvite
+// CANCEL a previously sent INVITE.
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::CancelInviteL()
+	{
+	iCurrentState->CancelInviteL( *this );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::AcceptInvite
+// Accept a received INVITE with 200 (OK).
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::AcceptInviteL(const TInetAddr& aIPAddr )
+	{
+	iLocalAddr = aIPAddr;
+	iCurrentState->AcceptInviteL( *this );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::DeclineInvite
+// Decline a received INVITE with 486 (Busy Here).
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::DeclineInviteL()
+	{
+	iCurrentState->DeclineInviteL( *this );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::EndSession
+// End the dialog with BYE.
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::EndSessionL()
+	{
+	iCurrentState->EndSessionL( *this );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CreateIML
+// Create and send an Instant Message to recipient defined with parameter.
+// This is implemented with the MESSAGE method and is sent outside of a
+// dialog.
+// -----------------------------------------------------------------------------
+EXPORT_C void CSIPExSIPEngine::CreateIML( 
+    const TDesC8& aMessage,
+	const TDesC8& aSipUri )
+	{
+	_LIT8( KMediaType, "SIPEx" );	// Part of content type
+	_LIT8( KMediaSubType, "InstantMessage" );	// Part of content type
+
+	// Create the necessary elements of the IM
+	CSIPRequestElements* reqElem = CreateReqElementsLC( aSipUri );
+	CSIPToHeader* toHeader = CreateToHeaderLC( aSipUri );
+	reqElem->SetToHeaderL( toHeader );
+	CleanupStack::Pop( toHeader );
+
+    // Create the From header value using info from the profile
+    const TDesC8* aor = NULL;
+    iProfile->GetParameter( KSIPUserAor, aor ); 
+	__ASSERT_ALWAYS( aor && *aor != KNullDesC8, User::Leave( KErrNotFound ) );
+
+    CSIPAddress* addr = CSIPAddress::DecodeL( *aor );
+	CleanupStack::PushL( addr );
+    CSIPFromHeader* fromHeader = CSIPFromHeader::NewL( addr );
+	CleanupStack::Pop( addr );
+
+	CleanupStack::PushL( fromHeader );
+	reqElem->SetFromHeaderL( fromHeader );
+	CleanupStack::Pop( fromHeader );
+	
+
+	reqElem->SetMethodL( SIPStrings::StringF( SipStrConsts::EMessage ) );
+
+	// Get reference to the message elements from the request
+	// elements, create and insert content type header (ownership
+	// of the content type object is transferred)
+	CSIPMessageElements& msgElem = reqElem->MessageElements();
+	CSIPContentTypeHeader* ct =
+   		CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
+	msgElem.SetContentL( aMessage.AllocL(), ct );
+	CleanupStack::Pop( ct );
+
+	// Get the current connection
+	CSIPConnection& conn = ConnectionL();
+
+	// Send the request using the connection (ownership of the
+	// request elements object is transferred)
+	CSIPClientTransaction* ctx = conn.SendRequestL( reqElem );
+	CleanupStack::Pop( reqElem );
+
+	delete ctx;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IMReceivedL
+// An Instant Message is received from the network. Respond with 200 (OK)
+// and alert the Engine Observer.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IMReceivedL( CSIPServerTransaction* aTransaction  )
+	{
+	const CSIPRequestElements* reqElem = aTransaction->RequestElements();
+	const CSIPFromHeader* fromHeader = reqElem->FromHeader();
+	
+    CSIPResponseElements* respElem =
+    	CSIPResponseElements::NewLC( 200, 
+    	    SIPStrings::StringF( SipStrConsts::EPhraseOk ) );
+	// Use the transaction to send 200 (OK)
+	aTransaction->SendResponseL( respElem );
+	CleanupStack::Pop( respElem );
+
+	// Inform the observer of the Instant Message
+	iObserver->IMReceived(
+	    fromHeader->SIPAddress().Uri8().Uri().Extract( EUriUserinfo ),
+		reqElem->MessageElements().Content());	
+
+	// We no longer need aTransaction. Just delete it.
+	delete aTransaction;
+	aTransaction = NULL;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IMReceived
+// Call the IMReceivedL method, trapping the possible errors.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IMReceived( CSIPServerTransaction* aTransaction  )
+	{
+	TRAPD( err, IMReceivedL( aTransaction ));
+
+	if ( err != KErrNone )
+		{
+		iObserver->EngineError( err );
+		}
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SetCurrentState
+// Sets the new current state of the state machine.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::SetCurrentState( CSIPExSIPStateBase* aState )
+	{
+	iCurrentState = aState;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ConnectionL
+// Returns the active connection.
+// -----------------------------------------------------------------------------
+CSIPConnection& CSIPExSIPEngine::ConnectionL()
+	{
+	CSIPConnection* conn = CurrentConnection();
+	if ( !conn )
+		{
+		TUint32 iapId( 0 );
+	    User::LeaveIfError( iProfile->GetParameter( KSIPAccessPointId, iapId ) );
+		iConnection = CSIPConnection::NewL( *iSIP, iapId, *this );
+		return *iConnection;
+		}
+	return *conn;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::Profile
+// Returns the enabled profile.
+// -----------------------------------------------------------------------------
+CSIPProfile& CSIPExSIPEngine::Profile()
+	{
+	return *iProfile;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SetServerTx
+// Sets the current Server Transaction.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::SetServerTx( CSIPServerTransaction* aTx )
+	{
+	delete iServerTx;
+	iServerTx = aTx;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ServerTx
+// Returns the current Server Transaction.
+// -----------------------------------------------------------------------------
+CSIPServerTransaction& CSIPExSIPEngine::ServerTx()
+	{
+	return *iServerTx;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SetClientTx
+// Sets the current Client Transaction.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::SetClientTx( CSIPClientTransaction* aTx )
+	{
+	delete iClientTx;
+	iClientTx = aTx;
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ClearClientTx
+// Deletes the current Client Transaction.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ClearClientTx()
+	{
+	delete iClientTx;
+	iClientTx = NULL;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ClientTx
+// Returns the current Client Transaction.
+// -----------------------------------------------------------------------------
+CSIPClientTransaction& CSIPExSIPEngine::ClientTx()
+	{
+	return *iClientTx;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SetDialogAssoc
+// Sets the current Invite Dialog Association.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::SetDialogAssoc( CSIPInviteDialogAssoc& aAssoc )
+	{
+	delete iDialogAssoc;
+	iDialogAssoc = &aAssoc;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::DialogAssoc
+// Returns the current Invite Dialog Association.
+// -----------------------------------------------------------------------------
+CSIPInviteDialogAssoc& CSIPExSIPEngine::DialogAssoc()
+	{
+	return *iDialogAssoc;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CreateToHeaderLC
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+CSIPToHeader* CSIPExSIPEngine::CreateToHeaderLC( const TDesC8& aSipUri )
+	{
+	CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri );
+	CleanupStack::PushL( addr );
+	
+	CSIPToHeader* to = CSIPToHeader::NewL( addr );
+	CleanupStack::Pop( addr );
+	CleanupStack::PushL( to );
+
+	return to;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CreateReqElementsLC
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------	
+CSIPRequestElements* CSIPExSIPEngine::CreateReqElementsLC( const TDesC8& aSipUri )
+    {
+    CUri8* uri8 = ConvertToUri8LC( aSipUri );
+    CSIPRequestElements* req = CSIPRequestElements::NewL( uri8 );
+    CleanupStack::Pop( uri8 );
+    CleanupStack::PushL( req );
+    return req;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CreateMessageElementsLC
+// Create a CSIPMEssageElements instance with the required information.
+// -----------------------------------------------------------------------------
+CSIPMessageElements* CSIPExSIPEngine::CreateMessageElementsLC()
+	{
+	_LIT8( KMediaType, "application" );
+	_LIT8( KMediaSubType, "sdp" );
+
+	CSIPMessageElements* msgElements = CSIPMessageElements::NewLC();
+
+	CSdpDocument* sdpDocument = SdpDocumentLC();
+	MediaFieldsL( sdpDocument );
+
+    HBufC8* content = SdpBodyL( sdpDocument );
+    CleanupStack::PushL( content );
+
+   	CSIPContentTypeHeader* ct =
+   		CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
+
+	msgElements->SetContentL( content, ct );
+
+	CleanupStack::Pop( ct );
+	CleanupStack::Pop( content );
+	CleanupStack::PopAndDestroy( sdpDocument );
+
+	return msgElements;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ConvertToUri8LC
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------  
+CUri8* CSIPExSIPEngine::ConvertToUri8LC( const TDesC8& aSipUri )
+    {
+    TUriParser8 parser;
+    User::LeaveIfError( parser.Parse( aSipUri ) ); 
+    CUri8* uri8 = CUri8::NewLC( parser );
+    return uri8; 
+    }
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SessionId
+// Set the session ID using a random number if not set before. Return ID.
+// -----------------------------------------------------------------------------
+TInt64 CSIPExSIPEngine::SessionId()
+	{
+	if ( iSessionId > 0 )
+		{
+		return iSessionId;
+		}
+	else
+		{
+		// Create a random number as the session ID
+		TTime now;
+		now.HomeTime();
+		TInt64 seed = now.Int64();
+
+		TInt random = Math::Rand( seed );
+		iSessionId = random;
+		return iSessionId;
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SdpDocumentLC
+// Create an instance of the SDP Document class, set the required fields, and
+// leave it on the cleanup stack. Return pointer to the SDP Document instance.
+// Ownership is transferred.
+// -----------------------------------------------------------------------------
+CSdpDocument* CSIPExSIPEngine::SdpDocumentLC()
+	{
+	_LIT8( KSessionName, "SIP Example Application" );
+
+	// Create SDP document
+	CSdpDocument* sdpDocument = CSdpDocument::NewL();
+	CleanupStack::PushL( sdpDocument );
+
+	CSdpOriginField* orgField = CSdpOriginField::NewL( KSdpNoInfoDesC8(), 
+													   SessionId(), 0,
+													   iLocalAddr );
+	sdpDocument->SetOriginField( orgField );
+
+	// Set session name
+	sdpDocument->SetSessionNameL( KSessionName );
+
+	// Set connection data
+	CSdpConnectionField* connField = CSdpConnectionField::NewL( iLocalAddr );
+	sdpDocument->SetConnectionField( connField );
+
+	return sdpDocument;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::MediaFieldsL()
+// Insert the media line to the SDP document given as parameter.
+// The format of the media line is:
+//     application 0 TCP SIPEx
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::MediaFieldsL( CSdpDocument* aDocument )
+	{
+	_LIT8( KFormat, "SIPEx" );
+
+	// Set media field
+	// Set media type: application
+	RStringF media = StringPoolL().StringF( SdpCodecStringConstants::EMediaApplication, 
+					                        SdpCodecStringPool::StringTableL() );
+	// Set media transport: TCP
+	RStringF prot = StringPoolL().StringF( SdpCodecStringConstants::EProtocolTcp,
+				                           SdpCodecStringPool::StringTableL() );
+	// Create the media line
+	CSdpMediaField* mediaDescription =
+		CSdpMediaField::NewL( media, 0, prot, KFormat );
+
+	aDocument->MediaFields().Append( mediaDescription );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::SdpBodyL()
+// Return SDP message body in textual form.
+// Ownership is transferred.
+// -----------------------------------------------------------------------------
+HBufC8* CSIPExSIPEngine::SdpBodyL( CSdpDocument* aDocument )
+	{
+	HBufC8* sdpBuf = NULL;
+
+	// Build the message body using buffer writer
+	if ( aDocument->IsValid() )
+		{
+		CBufFlat* enBuf = CBufFlat::NewL( 1000 );
+		CleanupStack::PushL( enBuf );
+		RBufWriteStream writeStream;
+		writeStream.Open( *enBuf, 0 );
+		aDocument->EncodeL( writeStream );
+		writeStream.Close();
+		TPtr8 ptr = enBuf->Ptr( 0 );
+		sdpBuf = ptr.AllocL();
+		CleanupStack::PopAndDestroy( enBuf );
+		writeStream.Close();
+		}
+
+	return sdpBuf;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::CurrentConnection
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+CSIPConnection* CSIPExSIPEngine::CurrentConnection()
+    {
+    if ( iConnection )
+        {
+        return iConnection;
+        }
+        
+    return 0;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IPAddressFromResponseElementsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+const TInetAddr CSIPExSIPEngine::IPAddressFromResponseElementsL(
+	const CSIPResponseElements& aRespElem )
+	{
+	;
+	// First, retrieve remote party IP Address
+	// Get Message Elements from Response Elements
+	const CSIPMessageElements& msgElem = aRespElem.MessageElements();
+
+	// Get message content from Message Elements
+	const TDesC8& content = msgElem.Content();
+
+	// Get the SDP Document from the message content		
+	CSdpDocument* SDPDoc = CSdpDocument::DecodeLC( content );
+
+	// Get the Connection Field from the SDP Document
+	CSdpConnectionField* connField = SDPDoc->ConnectionField();
+
+	// And, finally, get the IP Address from the Connection Field
+	const TInetAddr* addr = connField->InetAddress();
+	const TInetAddr inetAddr = *addr;
+
+	CleanupStack::PopAndDestroy( SDPDoc );
+
+	return inetAddr;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::StringPoolL
+// Get SDP codec string pool. Open string pool if not opened.
+// -----------------------------------------------------------------------------
+RStringPool CSIPExSIPEngine::StringPoolL()
+	{
+	TRAPD( error, SdpCodecStringPool::OpenL() );
+	if ( error == KErrAlreadyExists )
+		{
+		return SdpCodecStringPool::StringPoolL();
+		}
+	else if ( error == KErrNone )
+		{
+		//Add missing string to the pool then return it
+		return SdpCodecStringPool::StringPoolL();
+		}
+	else
+		{
+		User::Leave( error );
+		return SdpCodecStringPool::StringPoolL(); //Return here to omit warning
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::Observer
+// Return pointer to the class registered as Engine Observer.
+// -----------------------------------------------------------------------------
+MSIPExSIPEngineObserver* CSIPExSIPEngine::Observer()
+	{
+	return iObserver;
+	}
+
+
+
+
+//
+// IMPLEMENTATION OF THE METHODS INHERITED FROM BASE CLASSES
+//
+
+// From MSIPObserver:
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingRequest
+// Handle a request coming outside of a SIP dialog.
+// We have to use TRAPs because this is a non-leaving method.
+// We get the ownership to aTransaction.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingRequest( 
+    TUint32 aIapId,
+	CSIPServerTransaction* aTransaction )
+	{
+	if ( !iProfile )
+		{
+		TRAPD( err, EnableProfileL() );
+
+		if ( err != KErrNone )
+			{
+			// A profile error occured.
+			// Delete aTransaction and inform the observer.
+			delete aTransaction;
+			aTransaction = NULL;
+
+			iObserver->ProfileError( err );
+			return;
+			}
+		}
+	
+	if ( !CurrentConnection() )
+		{
+		// Create an instance of the SIP Connection object.
+		TRAPD( err2, iConnection = CSIPConnection::NewL( *iSIP, aIapId, *this ) );
+
+		if ( err2 != KErrNone )
+			{
+			// An error occured opening the connection.
+			// Delete aTransaction and inform the observer.
+			delete aTransaction;
+			aTransaction = NULL;
+
+			iObserver->EngineError( err2 );
+			return;
+			}
+		} 
+
+	if ( aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+		{
+		// An INVITE has been received.
+		// Save the pointer for later queries and eventual
+		// deletion.
+		SetServerTx(aTransaction);
+
+		// Let the current state handle the received INVITE.
+		// Ownership of aTransaction is transferred.
+		TRAPD( err2, iCurrentState->InviteReceivedL( *this, aTransaction ) );
+		if ( err2 != KErrNone )
+			{
+			// An error occured when handling invitation.
+			// Delete aTransaction and inform the observer.
+			delete aTransaction;
+			iServerTx = NULL;
+			iObserver->EngineError( err2 );
+			return;
+			}
+		}
+	else if ( aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EMessage ) )
+		{
+		IMReceived( aTransaction );
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::TimedOut - No implementation needed
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::TimedOut(
+	CSIPServerTransaction& /* aSIPServerTransaction */ )
+	{
+	}
+
+
+// From MSIPConnectionObserver:
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingRequest
+// No dialog has been established yet, so this should be an INVITE or MESSAGE.
+// The ownership of aTransaction is transferred.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingRequest( CSIPServerTransaction* aTransaction )
+	{
+    if ( aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+        {
+		// An INVITE has been received.
+		// Get profile, create connection, and let the
+		// state machine handle it.
+
+		if ( !iProfile )
+			{
+			// If the default profile isn't enabled, do it now
+			TRAPD( err, EnableProfileL() );
+
+			if ( err != KErrNone )
+				{
+				// A profile error occured.
+				// Delete aTransaction and inform the observer.
+				delete aTransaction;
+				aTransaction = NULL;
+
+				iObserver->ProfileError( err );
+				}
+			}
+
+		// The transaction still exists, which means there
+		// was no trouble with the profile part. Go on with
+		// request handling.
+		if ( aTransaction )
+			{
+			// The ownership of aTransaction is transferred.
+			// Save the pointer for later queries and eventual
+			// deletion.
+			SetServerTx(aTransaction);
+
+			// Handle the incoming request in the state machine classes
+			// The ownership of aTransaction is transferred.
+			TRAPD( err2, iCurrentState->InviteReceivedL( *this, aTransaction ));
+			}
+        }
+    else if ( aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EMessage ) )
+    	{
+    	// An Instant Message is received
+		// The state machine isn't needed for this.
+    	IMReceived( aTransaction );
+    	}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingRequest
+// A request concerning an established dialog is received.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingRequest( 
+    CSIPServerTransaction* aTransaction,
+	CSIPDialog& aDialog )
+	{
+	const RPointerArray<CSIPDialogAssocBase>& dialogAssoc =
+    	aDialog.SIPDialogAssociations();
+
+	for ( TInt i = 0; i < dialogAssoc.Count(); i++ )
+		{
+		if ( dialogAssoc[i]->Type() == 
+		    SIPStrings::StringF( SipStrConsts::EInvite ) )
+			{
+			iDialogAssoc = 
+			    reinterpret_cast<CSIPInviteDialogAssoc*>( dialogAssoc[0] );
+			break;
+			}
+		}
+
+    if ( aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EBye ) )
+        {
+		// The ownership of aTransaction is transferred.
+		// Save the pointer for later queries and eventual
+		// deletion.
+		SetServerTx(aTransaction);
+
+        TRAPD( err, iCurrentState->ByeReceivedL( *this, *aTransaction ) );
+
+        if ( err != KErrNone )
+        	{
+        	iObserver->EngineError( err );
+        	}
+        }
+    else if ( aTransaction->Type() == 
+        SIPStrings::StringF( SipStrConsts::EAck ) )
+        {
+		// The ownership of aTransaction is transferred.
+		// Save the pointer for later queries and eventual
+		// deletion.
+		SetServerTx(aTransaction);
+
+        TRAPD( err, iCurrentState->AckReceivedL( *this, *aTransaction ) );
+
+        if ( err != KErrNone )
+        	{
+        	iObserver->EngineError( err );
+        	}
+        }
+    else if ( aTransaction->Type() == 
+        SIPStrings::StringF( SipStrConsts::EMessage ) )
+    	{
+    	IMReceived( aTransaction );
+    	}
+    else
+        {
+        // Unknown, or unimplemented, request received
+		delete aTransaction;
+		aTransaction = NULL;
+        iObserver->EngineError( KErrNotSupported );
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingResponse - No implementation needed
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingResponse( 
+    CSIPClientTransaction& /* aTransaction */ )
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingResponse
+// A response inside an established dialog is received.
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+										CSIPDialogAssocBase& aDialogAssoc )
+	{
+	if ( aDialogAssoc.Type() == SIPStrings::StringF( SipStrConsts::EInvite )  )
+		{
+		iDialogAssoc = reinterpret_cast<CSIPInviteDialogAssoc*>( &aDialogAssoc );
+		}
+	
+	TRAPD( err, iCurrentState->ResponseReceivedL( *this, aTransaction ) );
+	
+	if ( err != KErrNone )
+		{
+		iObserver->EngineError( err );
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingResponse
+// Since the ownership is transferred, aDialogAssoc needs to be deleted
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingResponse( 
+    CSIPClientTransaction& /* aTransaction */,
+	CSIPInviteDialogAssoc* aDialogAssoc )
+	{
+	delete aDialogAssoc;
+	aDialogAssoc = NULL;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::IncomingResponse - No implementation needed
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::IncomingResponse( 
+    CSIPClientTransaction& /* aTransaction */,
+	CSIPRegistrationBinding& /* aRegistration */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */,
+	CSIPTransactionBase& /* aTransaction */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */,
+	CSIPClientTransaction& /* aTransaction */,
+	CSIPRegistrationBinding& /* aRegistration */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */,
+	CSIPTransactionBase& /* aTransaction */,
+	CSIPDialogAssocBase& /* aDialogAssoc */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */, 
+    CSIPRefresh& /* aSIPRefresh */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */,
+	CSIPRegistrationBinding& /* aRegistration */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ErrorOccured
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ErrorOccured( 
+    TInt /* aError */,
+	CSIPDialogAssocBase& /* aDialogAssoc */ )
+	{
+	
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::InviteCompleted
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::InviteCompleted( 
+    CSIPClientTransaction& /* aTransaction */ )
+	{
+	delete iClientTx;
+	iClientTx = NULL;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::InviteCanceled
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::InviteCanceled( 
+    CSIPServerTransaction& /* aTransaction */ )
+    {
+    iCurrentState->CancelReceivedL( *this, *iClientTx );
+    delete iClientTx; 
+	iClientTx = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ConnectionStateChanged
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ConnectionStateChanged( CSIPConnection::TState aState )
+	{
+	if ( iConnState == CSIPConnection::EActive &&
+		 aState != CSIPConnection::EActive )
+		{
+		// A previously active connection is active no more
+		iObserver->ConnectionLost();
+		}
+	else
+		{
+		iConnState = aState;
+		}
+	}
+
+
+
+// From MSIPProfileRegistryObserver
+
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ProfileRegistryErrorOccurred
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ProfileRegistryEventOccurred( 
+    TUint32 aProfileId, 
+    TEvent aEvent )
+    {
+    switch (aEvent)
+	    {
+	    case MSIPProfileRegistryObserver::EProfileRegistered:
+	        {
+	        HandleProfileRegistered( aProfileId );
+	        break;
+	        }
+	    case MSIPProfileRegistryObserver::EProfileDeregistered:
+	        {
+	        HandleProfileDeregistered( aProfileId );
+	        break;
+	        }
+	    case MSIPProfileRegistryObserver::EProfileDestroyed:
+	        {
+            HandleProfileDestroyed( aProfileId );
+	        break;
+	        }
+	    default:
+	        {
+	        // MSIPProfileRegistryObserver::EProfileCreated and
+	        // MSIPProfileRegistryObserver::EProfileUpdated
+	        // are ignored
+	        break;
+	        }
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::ProfileRegistryErrorOccurred
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::ProfileRegistryErrorOccurred( 
+    TUint32 /* aSIPProfileId */,
+	TInt aError )
+	{
+	iObserver->ProfileError( aError );
+	}
+	
+
+	
+// Private handling for profile events
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::HandleProfileRegistered
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::HandleProfileRegistered( TUint32 aSIPProfileId )
+	{
+    TUint32 profileId( 0 );
+	iProfile->GetParameter( KSIPProfileId, profileId );
+    if ( aSIPProfileId == profileId )
+        {
+		// The profile registration is complete
+		// Inform the Engine Observer
+		iObserver->ProfileEnabled( aSIPProfileId );
+        }
+	}
+	
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::HandleProfileDeregistered
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::HandleProfileDeregistered( TUint32 aSIPProfileId )
+	{
+	TUint32 profileId( 0 );
+	iProfile->GetParameter( KSIPProfileId, profileId );
+    if ( aSIPProfileId == profileId )
+        {
+		// The previously registered profile has
+		// become unregistered.
+    	delete iDialogAssoc;
+    	iDialogAssoc = 0;
+    	delete iConnection;
+    	iConnection = 0;
+    	//iNotOwnedConnection = 0;
+    	delete iProfile;
+    	iProfile = 0;
+    	
+    	iObserver->ProfileError( KErrGeneral );     	
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPExSIPEngine::HandleProfileDestroyed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CSIPExSIPEngine::HandleProfileDestroyed( TUint32 /* aSIPProfileId */ )
+	{
+	delete iDialogAssoc;
+	iDialogAssoc = 0;
+	delete iConnection;
+	iConnection = 0;
+	//iNotOwnedConnection = 0;
+	delete iProfile;
+	iProfile = 0;
+
+	iObserver->ProfileError( KErrGeneral );
+	}
+	
+// End of file