--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/sipapi/src/SipDialogImplementation.h Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,701 @@
+/*
+* Copyright (c) 2006-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:
+* Name : SipDialogImplementation.h
+* Part of : SIP Client
+* Interface : SDK API, SIP Client API
+* Version : 1.0
+*
+*/
+
+
+
+
+/**
+ @internalComponent
+*/
+
+
+#ifndef CSIPDIALOGIMPLEMENTATION_H
+#define CSIPDIALOGIMPLEMENTATION_H
+
+// INCLUDES
+#include <e32base.h>
+#include <stringpool.h>
+#include "sipdialog.h"
+#include "siptransactionbase.h"
+#include "_sipcodecdefs.h"
+
+// FORWARD DECLARATIONS
+class CSIPConnection;
+class CSIPConnectionImplementation;
+class MSIPRegistrationContext;
+class CSIPDialogAssocBase;
+class CSIPDialogAssocImplementation;
+class CSIPInviteDialogAssoc;
+class CSIPSubscribeDialogAssoc;
+class CSIPNotifyDialogAssoc;
+class CSIPReferDialogAssoc;
+class CSIPMessageElements;
+class CSIPRefresh;
+class CSIPClientTransaction;
+class CSIPServerTransaction;
+class CDialogState;
+class CSIPFromToHeaderBase;
+class CSIPFromHeader;
+class CSIPToHeader;
+class CUri8;
+class CSIPContactHeader;
+class CSIPCallIDHeader;
+class CConnectionCallback;
+
+// CLASS DECLARATION
+
+/**
+* Implementation class for managing SIP dialogs.
+*/
+class CSIPDialogImplementation: public CBase
+ {
+ public: // Constructors and destructor
+
+ /**
+ * Creates a new CSIPDialogImplementation, and pushes it to cleanupstack.
+ * @param aConnImplementation Connection implementation to use with the
+ * new dialog.
+ * @param aContext Registration context whose outbound proxy and other
+ * parameters are to be used. If NULL, context isn't used.
+ * Ownership is not transferred.
+ * @return New object, ownership is transferred.
+ */
+ static CSIPDialogImplementation*
+ NewLC(CSIPConnectionImplementation& aConnImplementation,
+ const MSIPRegistrationContext* aContext=0);
+
+ /**
+ * Two-phased constructor.
+ * This constructor should be used if the user has received
+ * SIP request that creates a SIP dialog association.
+ *
+ * @param aDialog Dialog which creates this CSIPDialogImplementation.
+ * Ownership is transferred.
+ * @param aConnImplementation Implementation of the used SIP connection
+ * @return New object, ownership is transferred.
+ */
+ static CSIPDialogImplementation*
+ NewL(CSIPDialog* aDialog,
+ CSIPConnectionImplementation& aConnImplementation);
+
+ /**
+ * Two-phased constructor
+ * This constructor should be used if the user has received
+ * SIP request that creates a SIP dialog association.
+ *
+ * @param aDialog Dialog which creates this CSIPDialogImplementation.
+ * Ownership is transferred.
+ * @param aConnImplementation Implementation of the used SIP connection
+ * @param aContext Registration context whose outbound proxy and other
+ * parameters are to be used.
+ * @return New object, ownership is transferred.
+ */
+ static CSIPDialogImplementation*
+ NewL(CSIPDialog* aDialog,
+ CSIPConnectionImplementation& aConnImplementation,
+ const MSIPRegistrationContext& aContext);
+
+ /**
+ * Destructor
+ */
+ ~CSIPDialogImplementation();
+
+ public: // New functions
+
+ /**
+ * Gets dialog state
+ * @return dialog state
+ */
+ CSIPDialog::TState State() const;
+
+ /**
+ * Gets all dialog associations.
+ * @return All dialog associations. Ownership of the array or the items
+ * inside it, is not transferred.
+ */
+ const RPointerArray<CSIPDialogAssocBase>& SIPDialogAssociations() const;
+
+ /**
+ * Gets used registration context for this dialog
+ * @return associated registration or 0-pointer otherwise.
+ * Ownership is not transferred.
+ */
+ const MSIPRegistrationContext* RegistrationContext() const;
+
+ /**
+ * Checks if the dialog association belongs to this dialog
+ * @param aAssoc a dialog association
+ * @return ETrue if belongs, EFalse otherwise
+ */
+ TBool IsAssociated(const CSIPDialogAssocBase& aAssoc) const;
+
+ /**
+ * Gets the SIP connection used for this dialog
+ * @return SIP connection used for the dialog, or 0-pointer if the
+ * connection has been deleted. Ownership isn't transferred.
+ */
+ CSIPConnection* Connection();
+
+ /**
+ * Gets the SIP connection used for this dialog.
+ * @return SIP connection used for the dialog, or 0-pointer if the
+ * connection has been deleted. Ownership isn't transferred.
+ */
+ const CSIPConnection* Connection() const;
+
+ /**
+ * Gets originator's address
+ * @return originator's address (From-header)
+ */
+ const CSIPFromHeader& FromHeader() const;
+
+ /**
+ * Gets recipient's address
+ * @return recipient's address (To-header)
+ */
+ const CSIPToHeader& ToHeader() const;
+
+ /**
+ * Gets remote-uri used during dialog creation
+ * @return Remote target uri
+ */
+ const CUri8& RemoteURI() const;
+
+ /**
+ * Gets the Call-ID of the dialog.
+ * @return Call-ID
+ */
+ const CSIPCallIDHeader& CallIdL() const;
+
+ /**
+ * Get the Call-ID from SIP Client and store it.
+ */
+ void StoreCallIdL();
+
+ /**
+ * Copies Call-ID from aDialog.
+ * @pre iCallID == NULL
+ * @param aDialog CSIPDialogImplementation where the Call-ID is copied
+ * from.
+ */
+ void CopyCallIdL(const CSIPDialogImplementation& aDialog);
+
+ /**
+ * Compares this object to another object
+ * @param aDialog CSIPDialogImplementation object to compare
+ * @returns ETrue if the objects are equal, otherwise EFalse
+ */
+ TBool operator==(const CSIPDialogImplementation& aDialog) const;
+
+ TInt ReuseInitialRequestData();
+
+ CSIPDialog& Dialog();
+
+ TBool IncomingResponseL(CSIPResponseElements* aElements,
+ TUint32 aRequestId,
+ TUint32 aDialogId,
+ CConnectionCallback& aCallback);
+
+ TBool IncomingResponseL(CSIPResponseElements* aElements,
+ TUint32 aRequestId,
+ TUint32 aRefreshId,
+ TUint32 aDialogId,
+ CConnectionCallback& aCallback);
+
+ TBool ResponseToRefreshL(CSIPResponseElements* aElements,
+ TUint32 aRequestId,
+ TUint32 aRefreshId,
+ CConnectionCallback& aCallback,
+ const CDialogState& aEarly,
+ const CDialogState& aConfirmed,
+ const CDialogState& aTerminated,
+ TBool aIsConfirmed=EFalse);
+
+ /**
+ * Handle an incoming SIP request.
+ *
+ * @param aTransaction Server transaction, ownership is transferred.
+ * @param aCallback For selecting a callback function and its parameters
+ * @return ETrue if the caller should make a callback function call,
+ * EFalse otherwise
+ */
+ TBool IncomingRequestL(CSIPServerTransaction* aTransaction,
+ CConnectionCallback& aCallback);
+
+ TBool ErrorOccured(TInt aError,
+ TUint32 aRequestId,
+ CConnectionCallback& aCallback);
+
+ TBool ErrorOccured(TInt aError,
+ TUint32 aRefreshId,
+ TUint32 aRequestId,
+ CConnectionCallback& aCallback);
+
+ /**
+ * Obtains the dialog id.
+ *
+ * @return TSIPDialogId
+ */
+ TUint32 DialogId() const;
+
+ /**
+ * Set the dialog id.
+ *
+ * @param aDialogId Dialog id
+ */
+ void SetDialogId(TUint32 aDialogId);
+
+ /**
+ * Searches for a transaction having the specified id.
+ *
+ * @param aRequestId Identifier used for searching the transaction.
+ * @return CSIPTransactionBase The found transaction or NULL if
+ * transaction wasn't found. Ownership is not transferred.
+ */
+ CSIPTransactionBase* FindTransaction(TUint32 aRequestId) const;
+
+ /**
+ * Searches for a transaction having the specified id.
+ *
+ * @param aRequestId Identifier used for searching the transaction
+ * @param aTransaction OUT: pointer is set to the found transaction
+ * @param aAssoc OUT: pointer is set to the dialog association related
+ * to the found transaction
+ * @return ETrue if found. EFalse if not found, in this case aTransaction
+ * and aAssoc haven't been set.
+ */
+ TBool FindTransactionAndAssoc(TUint32 aRequestId,
+ CSIPTransactionBase** aTransaction,
+ CSIPDialogAssocBase** aAssoc) const;
+
+ /**
+ * Searches for the dialog association and refresh by the aRefreshId.
+ *
+ * @param aRefreshId RefreshId
+ * @param OUT: Dialog association, if found
+ * @param OUT: aRefresh CSIPRefresh, if found
+ * @return ETrue if a matching refresh and dialog association were
+ * found, EFalse otherwise
+ */
+ TBool FindAssocAndRefresh(TUint32 aRefreshId,
+ CSIPDialogAssocBase** aAssoc,
+ CSIPRefresh** aRefresh) const;
+
+ /**
+ * Searches for the dialog association, refresh and transaction.
+ * Both aRequestId and aRefreshId are used for search, because either
+ * of them might not yet be stored in the SIP API.
+ *
+ * @param aRequestId RequestId
+ * @param aRefreshId RefreshId
+ * @param aAssoc OUT: Dialog association, if found
+ * @param aRefresh OUT: CSIPRefresh, if found
+ * @param aTransaction OUT: Transaction, if found
+ * @return ETrue if a matching dialog association and refresh were
+ * found, EFalse otherwise
+ */
+ TBool FindAssocAndRefreshL(TUint32 aRequestId,
+ TUint32 aRefreshId,
+ CSIPDialogAssocBase** aAssoc,
+ CSIPRefresh** aRefresh,
+ CSIPTransactionBase** aTransaction) const;
+ /**
+ * Finds a refresh by first the given request ID and the the refresh ID.
+ * All dialog associations are searched through.
+ *
+ * @param aRequestId RequestId associated with the refresh instance
+ * @param aRefreshId RefreshId associated with the refresh instance
+ *
+ * @return refresh or NULL if not found, ownership is not transferred.
+ */
+ CSIPRefresh* FindRefresh(TUint32 aRequestId,
+ TUint32 aRefreshId) const;
+
+ /**
+ * Changes the dialog's current state.
+ *
+ * @param aNewState State which dialog enters
+ */
+ void ChangeState(const CDialogState* aNewState);
+
+ /**
+ * Connection state is no longer available.
+ */
+ void ConnectionLost();
+
+ CSIPClientTransaction*
+ SendNonTargetRefreshRequestL(CSIPDialogAssocImplementation& aAssoc,
+ RStringF aMethod,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendInviteL(CSIPInviteDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendPrackL(CSIPInviteDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendUpdateL(CSIPInviteDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ void SendAckL(CSIPInviteDialogAssoc& aAssoc,
+ const CSIPClientTransaction& aTransaction,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendSubscribeL(CSIPSubscribeDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements,
+ CSIPRefresh* aRefresh) const;
+
+ CSIPClientTransaction*
+ UpdateL(CSIPSubscribeDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendUnsubscribeL(CSIPSubscribeDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ /**
+ * Send a SIP response to network. Application can't send a 100 response.
+ * That has already been checked by CSIPResponseElements.
+ * @param aElements Response elements
+ * @param aRequestId Identifies the request to which this response is for
+ * @param aAffectsDialogState Tells if the response can cause dialog to
+ * enter another state.
+ * @param aTargetRefresh Tells if this is a response to a target refresh
+ * request.
+ */
+ void SendResponseL(const CSIPResponseElements& aElements,
+ TUint32 aRequestId,
+ TBool aAffectsDialogState,
+ TBool aTargetRefresh=EFalse);
+
+ CSIPClientTransaction* SendByeL(CSIPInviteDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction* SendCancelL(TUint32 aRequestId) const;
+
+ CSIPClientTransaction*
+ SendNotifyL(CSIPNotifyDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ CSIPClientTransaction*
+ SendReferL(CSIPReferDialogAssoc& aAssoc,
+ CSIPMessageElements* aElements) const;
+
+ /**
+ * Add a dialog association to this dialog. A dialog can have only one
+ * INVITE association at a time.
+ * @param aAssoc Dialog association
+ * @param aType Type of the dialog association
+ * @leave KErrAlreadyExists If aAssoc is already associated with this
+ * dialog or if attempting to add another INVITE dialog
+ * association.
+ */
+ void AddAssocL(CSIPDialogAssocBase& aAssoc, RStringF aType);
+
+ /**
+ * Remove a dialog association from this dialog.
+ * When there are no associations left, the dialog is deleted.
+ * @param aAssoc Dialog association
+ */
+ void RemoveAssoc(const CSIPDialogAssocBase& aAssoc);
+
+ /**
+ * Informs CSIPDialogImplementation that the associated CSIPConnection
+ * has been deleted. After this the CSIPDialogImplementation object can't
+ * be used anymore.
+ */
+ void ConnectionDeleted();
+
+ void CheckNoTransactionExistsL() const;
+
+ /**
+ * Send a request that creates the dialog.
+ *
+ * @param aAssoc Dialog association which sends the request.
+ * @param aElements Message elements, can be NULL. Ownership is
+ * transferred.
+ * @param aRefresh Refresh object, if the request is to be refreshed.
+ * Ownership isn't transferred.
+ * @return Client transaction. Ownership is transferred.
+ */
+ CSIPClientTransaction*
+ SendDialogCreatingRequestL(CSIPDialogAssocImplementation& aAssoc,
+ CSIPMessageElements* aElements,
+ CSIPRefresh* aRefresh=0);
+
+ /**
+ * Sends a SIP request described by aElements withing dialog and creates
+ * a client transaction representing the request.
+ *
+ * @pre aMethod.Length() > 0
+ *
+ * @param aAssoc Dialog association with which the transaction will be
+ * associated
+ * @param aMethod SIP request method
+ * @param aElements Optional SIP message headers and body, can be NULL.
+ * Ownership is transferred.
+ * @return CSIPClientTransaction new transaction, ownership is
+ * transferred
+ */
+ CSIPClientTransaction*
+ SendRequestInDialogL(CSIPDialogAssocImplementation& aAssoc,
+ RStringF aMethod,
+ CSIPMessageElements* aElements) const;
+
+ /**
+ * Creates a client transaction.
+ *
+ * @param aType Transaction type
+ * @param aAssoc Dialog association with which the transaction will be
+ * associated
+ * @param aRefresh If transaction is refreshed, this points to a
+ * CSIPRefresh, otherwise this is NULL. Ownership is not transferred.
+ * @return CSIPClientTransaction new transaction, ownership is
+ * transferred
+ */
+ CSIPClientTransaction*
+ CreateClientTransactionL(RStringF aType,
+ CSIPDialogAssocImplementation& aAssoc,
+ CSIPRefresh* aRefresh) const;
+
+ /**
+ * Sets the dialog related headers when a SIP request that creates a SIP
+ * dialog association, is sent. Headers can be set only once.
+ * If aTo is NULL, aRemoteUri is used as To-header.
+ *
+ * @pre aRemoteUri != NULL &&
+ * iRemoteUri == NULL &&
+ * iFrom == NULL &&
+ * iTo == NULL &&
+ * iContact == NULL
+ * @param aFrom Originator's address, can be NULL. Ownership is
+ * transferred.
+ * @param aTo Recipient's address, can be NULL. Ownership is transferred
+ * @param aRemoteURI Remote target URI. ownership is transferred.
+ * @param aContact Contact to be used in dialog creation, can be NULL.
+ * Must be given only if user intends to re-direct future
+ * requests. Ownership is transferred.
+ */
+ void SetHeadersL(CSIPFromHeader* aFrom,
+ CSIPToHeader* aTo,
+ CUri8* aRemoteUri,
+ CSIPContactHeader* aContact);
+
+ /**
+ * Stores the To and From headers of the server transaction and marks
+ * the transaction to affect the dialog state.
+ *
+ * @pre
+ * @param aTransaction Server transaction which causes a dialog to be
+ * created.
+ */
+ void InitialTransactionReceivedL(CSIPServerTransaction& aTransaction);
+
+ const CSIPContactHeader* ContactHeader() const;
+
+ /**
+ * The dialog creating transaction has been initiated.
+ *
+ * @pre aRequestId != 0
+ * @pre iInitialRequestId == 0
+ * @post iInitialRequestId == aRequestId
+ *
+ * @param aRequestId RequestId of the transaction that creates the dialog
+ */
+ void InitialTransactionStarted(TUint32 aRequestId);
+
+ /**
+ * Determine if an incoming NOTIFY causes dialog to enter confirmed
+ * state.
+ *
+ * @return ETrue Dialog should enter confirmed state at the reception of
+ * NOTIFY. EFalse otherwise.
+ */
+ TBool DoesNotifyConfirmDialog() const;
+
+ /**
+ * Searches if there are dialog related requests, that are being
+ * refreshed. If found, those that are in state CSIPRefresh::EInactive
+ * are moved into CSIPRefresh::EActive state.
+ */
+ void ChangeRefreshesToActive() const;
+
+ /**
+ * If aMethod is a target refresh request, and aElements contains a
+ * Contact-header, the remote target URI of the dialog is updated.
+ *
+ * @param aMethod SIP request method
+ * @param aElements Message elements
+ */
+ void UpdateRemoteTargetL(RStringF aMethod,
+ const CSIPMessageElements& aElements);
+
+ /**
+ * Creates a copy of the URI in Contact-header, if aElements contains
+ * exactly one Contact-header.
+ *
+ * @param aElements Message elements
+ * @return Copy of the URI in Contact, or NULL if aElements doesn't have
+ * one Contact header. Ownership is transferred.
+ */
+ CUri8* GetUriFromContactL(const CSIPMessageElements& aElements) const;
+
+ /**
+ * Based on the received response, dialog may enter another state.
+ * A 100 response should not have a To-tag, so dialog won't
+ * enter Early-state when a 100 is received.
+ *
+ * @param aTransaction Client transaction carrying the received response
+ * @param aEarly Early-state of the dialog state machine
+ * @param aConfirmed Confirmed-state of the dialog state machine
+ * @param aTerminated Terminated-state of the dialog state machine
+ */
+ void UpdateState(const CSIPClientTransaction& aTransaction,
+ const CDialogState& aEarly,
+ const CDialogState& aConfirmed,
+ const CDialogState& aTerminated);
+
+ /**
+ * If the local tag is not yet known, obtain it from the SIP server via
+ * an ITC operation.
+ *
+ * @param aClientInitiatedDialog
+ * ETrue if the dialog creating request was sent by the local endpoint
+ * EFalse otherwise
+ */
+ void FillLocalTagL(TBool aClientInitiatedDialog) const;
+
+ /**
+ * If aToHeader has a tag parameter, the tag is stored as a remote-tag
+ * in the To-header of the dialog.
+ *
+ * @param aToHeader To-header of a response from remote endpoint.
+ */
+ void FillRemoteTagL(const CSIPToHeader& aToHeader) const;
+
+ TUint32 RegistrationId() const;
+
+ private: // Constructors, for internal use
+
+ CSIPDialogImplementation(
+ CSIPConnectionImplementation& aConnImplementation);
+
+ CSIPDialogImplementation(
+ CSIPConnectionImplementation& aConnImplementation,
+ const MSIPRegistrationContext& aContext);
+
+ void ConstructL(CSIPDialog* aDialog);
+
+ private: // New functions, for internal use
+
+ /**
+ * Checks that CSIPConnection is available for use (not NULL). If
+ * iConnection is NULL, it means user has deleted a resource needed by
+ * CSIPDialogImplementation, and this function leaves.
+ */
+ void CheckConnectionL() const;
+
+ CSIPConnection* GetConnection() const;
+
+ /**
+ * Returns the current dialog state. If state handler is not available,
+ * meaning user has deleted a resource needed by
+ * CSIPDialogImplementation, this function leaves.
+ */
+ const CDialogState& StateL() const;
+
+ /**
+ * Checks whether the dialog has an INVITE assocation.
+ *
+ * @return ETrue There is an INVITE association, EFalse otherwise
+ */
+ TBool HasInviteAssoc() const;
+
+ /**
+ * The dialog creating transaction has been created. The SIP responses
+ * to aTransaction will affect the state of dialog.
+ *
+ * @pre iInitialRequestId == 0
+ *
+ * @param aTransaction Transaction that creates the dialog.
+ */
+ void InitialTransactionStarted(CSIPTransactionBase& aTransaction);
+
+ private: // Data
+
+ //Dialog instance, Owned.
+ CSIPDialog* iDialog;
+
+ //DialogId received from SIP client
+ TUint32 iDialogId;
+
+ //Current dialog state. Not owned.
+ const CDialogState* iState;
+
+ //Initially zero. Is the requestId of the transaction that creates the
+ //dialog. RequestId is kept even after the transaction has been deleted.
+ TUint32 iInitialRequestId;
+
+ //Connection implementation associated with the dialog. Not owned.
+ //If NULL, application has deleted the CSIPConnection associated with
+ //the CSIPConnectionImplementation, and this CSIPDialogImplementation
+ //is useless as it can't use the CSIPConnection anymore.
+ CSIPConnectionImplementation* iConnection;
+
+ //Associated registration, can be NULL. Not owned.
+ const MSIPRegistrationContext* iRegistration;
+
+ //Dialog associations. Not owned.
+ RPointerArray<CSIPDialogAssocBase> iDialogAssocs;
+
+ //From header of the request that created the dialog. Owned.
+ CSIPFromHeader* iFrom;
+ //To header of the request that created the dialog. Owned.
+ CSIPToHeader* iTo;
+
+ //Remote target, can be NULL. Owned.
+ CUri8* iRemoteUri;
+
+ //Contact given by application. Will be deleted after the dialog
+ //creating request has been sent. Owned.
+ CSIPContactHeader* iContact;
+
+ //Call-ID of the dialog. Owned.
+ CSIPCallIDHeader* iCallID;
+
+ TBool iStringPoolOpened;
+
+ private: // For testing purposes
+
+ UNIT_TEST(CSIP_Test)
+ UNIT_TEST(CSIPInviteDialogAssoc_Test)
+ UNIT_TEST(CSIPSubscribeDialogAssoc_Test)
+ UNIT_TEST(CSIPReferDialogAssoc_Test)
+
+ void __DbgTestInvariant() const;
+
+ };
+
+#endif