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