diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/sipapi/src/SipDialogImplementation.h --- /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 +#include +#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& 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 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