--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/TransactionUser/src/UserAgentClient.h Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,651 @@
+/*
+* Copyright (c) 2007-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 : UserAgentClient.h
+* Part of : TransactionUser
+* Version : SIP/6.0
+*
+*/
+
+
+
+
+/**
+ @internalComponent
+*/
+
+#ifndef USERAGENTCLIENT_H
+#define USERAGENTCLIENT_H
+
+// INCLUDES
+#include "sipsecobserver.h"
+#include "MSIPServerResolverObserver.h"
+#include "CUserAgent.h"
+
+// FORWARD DECLARATIONS
+class RStringF;
+class CSIPViaHeader;
+class CSIPSec;
+class CRouteSet;
+class CResolvingResults;
+
+// CLASS DECLARATION
+
+/**
+ * This is a base class for all UACs.
+ */
+class CUserAgentClient :
+ public CUserAgent,
+ public MSIPServerResolverObserver,
+ public MSIPSecObserver
+ {
+public: // Destructor
+
+ virtual ~CUserAgentClient();
+
+public: // From CUserAgent
+
+ TBool IsUAS() const;
+
+protected: // From CUserAgent
+
+ virtual void CreateTransactionL() = 0;
+
+private: // From CUserAgent
+
+ TRegistrationId RegistrationId() const;
+
+ /**
+ * UAC detaches all references to the outgoing SIP message.
+ * Depending on the current state of UAC; it may need to stop as in
+ * certain states it cannot proceed without the outgoing SIP request.
+ *
+ * @post iOutgoingMsg = NULL
+ */
+ virtual void DetachOutgoingMsg();
+
+public: // From MSIPServerResolverObserver
+
+ void CompletedL();
+
+ void ErrorOccured(TInt aError);
+
+public: // From MSIPSecObserver
+
+ void SIPSecCacheUpdated(TBool aSuccess);
+
+public: //New functions
+
+ /**
+ * Handle a SIP request sent by upper layer. Request is checked, filled and
+ * the remote address is determined and resolved. Transaction related parts
+ * of the request are stored in CTransactionStore.
+ *
+ * @pre aReq != NULL
+ *
+ * @param aReq SIP request message. Ownership is transferred.
+ * @param aRegistrationId Registration id by which TU tries to find an
+ * outbound proxy for the request.
+ * @param aRemoteTarget Remote target of the request
+ * @param aResolve State the UAC will enter when it starts resolving URI
+ */
+ void HandleSendRequestL(CSIPRequest* aReq,
+ TRegistrationId aRegisterId,
+ const CURIContainer& aRemoteTarget,
+ const CUserAgentState& aResolve);
+
+ /**
+ * Handle a SIP response received from network.
+ *
+ * @pre aResp != NULL
+ *
+ * @param aResp SIP response, ownership is transferred
+ * @param aResolve State the UAC enters if it starts resolving URI
+ * @param aWaitResponse State the UAC enters if it sends the request again
+ * @param aWaitAckFromApp State InviteUAC enters if a 2xx response is
+ * passed to upper layer
+ * @param aWaitTransactionToEnd State InviteUAC enters if an error response
+ * is passed to upper layer
+ */
+ virtual void ReceiveResponseL(CSIPResponse* aResp,
+ const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse,
+ const CUserAgentState& aWaitAckFromApp,
+ const CUserAgentState& aWaitTransactionToEnd) = 0;
+
+ /**
+ * Sets the value for CUserAgent::iOwnsOutgoingMsg
+ *
+ * @param aOwnsRequest ETrue: UAC owns the request in the send buffer
+ * (CUserAgent::iOutgoingMsg), EFalse: UAC doesn't own the request.
+ */
+ void SetRequestOwnership(TBool aOwnsRequest);
+
+ /**
+ * Store the SIP response for asynchronous processing.
+ *
+ * @pre iIncomingMsg == NULL
+ *
+ * @param aResponse SIP response, ownership is transferred.
+ */
+ void StoreResponse(CSIPResponse* aResponse);
+
+ /**
+ * Pick the next remote address and transport protocol from the resolved
+ * addresses.
+ *
+ * @pre iOutgoingMsg != NULL && iResolvingResults != NULL
+ *
+ * @return ETrue if an address and protocol were found. EFalse if no more
+ * addresses are to try.
+ */
+ TBool SelectNextRemoteAddressL();
+
+ /**
+ * The remote address has now been resolved and UAC can send the SIP
+ * request to CTransaction.
+ *
+ * @param aNextState State where UAC moves after sending the request
+ */
+ void RemoteAddressResolvedL(const CUserAgentState& aNextState);
+
+ /**
+ * Returns information whether the UserAgent has passed a final response to
+ * the upper layer.
+ *
+ * @return ETrue: UAC has already passed a final response, no more
+ * responses can be passed. EFalse: final response not passed.
+ */
+ TBool FinalRespPassed() const;
+
+ /**
+ * Dummy timer used to make a synchronous SIPSec call to work as
+ * asynchronous, has completed.
+ */
+ void SIPSecTimerExpiredL();
+
+ /**
+ * SIPSec processing has been completed.
+ */
+ TInt SIPSecReady(TBool aSuccess);
+
+ /**
+ * SIPSec has completed updating the cache.
+ *
+ * @pre iIncomingMsg != NULL
+ * @post iIncomingMsg == NULL
+ *
+ * @param aSuccess status of the authorized SIP request
+ * ETrue: SIPSec has executed successfully
+ * EFalse: otherwise
+ * @param aResolve State the UAC enters if it starts resolving URI
+ * @param aWaitResponse State the UAC enters if it sends the request again
+ * @param aWaitAckFromApp State InviteUAC enters if a 2xx response is
+ * passed to upper layer
+ * @param aWaitTransactionToEnd State InviteUAC enters if an error response
+ * is passed to upper layer
+ * upper layer
+ */
+ void SIPSecCacheUpdatedL(TBool aSuccess,
+ const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse,
+ const CUserAgentState& aWaitAckFromApp,
+ const CUserAgentState& aWaitTransactionToEnd);
+
+ /**
+ * Offers the aResp to SIPSec for processing.
+ * Provisional responses are not offered.
+ *
+ * @pre iOutgoingMsg != NULL && iRemoteTarget != NULL
+ *
+ * @param aResp SIP response received from the network.
+ * @return ETrue SIPSec processes the response asynchronously.
+ * EFalse SIPSec has synchronously processed the response.
+ */
+ TBool PassResponseToSIPSecL(CSIPResponse& aResp);
+
+ /**
+ * If UAC has more remote addresses to try, updates the SIP request and
+ * sends it to the next address using a new CTransaction object.
+ *
+ * @param aError Reason why the next address will be tried. If aError is
+ * KErrNone, aResp must have a SIP response. If aError is not KErrNone,
+ * aResp must be NULL.
+ * @param aResolve State which UAC will enter if it decides to resolve the
+ * outbound proxy.
+ * @param aWaitResponse State which UAC enters if it decides to send
+ * request to the next ip-address.
+ * @param aResp If transaction ended because of SIP response, this is the
+ * response. Ownership is transferred if TryNextAddressL returns ETrue.
+ * @return value ETrue if the request will be sent to next address.
+ * Ownership of aResp has been taken.
+ * EFalse If request won't be sent again. Ownership of aResp has not been
+ * taken.
+ */
+ TBool TryNextAddressL(TInt aError,
+ const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse,
+ CSIPResponse* aResp = NULL);
+
+ /**
+ * UAC receives a response from network. Determines whether UAC should
+ * send the original request again, possibly to another address, or should
+ * UAC pass the response to upper layer.
+ *
+ * @pre aResp != NULL
+ *
+ * @param aResp SIP response. If UAC sends the original request again, the
+ * ownership of aResp is transferred.
+ * @param aResolve State which UAC enters if it decides to resolve the
+ * outbound proxy.
+ * @param aWaitResponse State which UAC enters if it decides to send
+ * request to the next ip-address.
+ * @return ETrue: UAC sends the request again and aResp isn't passed to
+ * upper layer. Ownership of aResp has been taken.
+ * EFalse: aResp should be passed to upper layer and it's ownership has
+ * not been taken.
+ */
+ TBool ShouldUaTryAgainL(CSIPResponse* aResp,
+ const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse);
+
+ /**
+ * CTransaction has ended before a final response was received
+ *
+ * @param aReason Reason why CTransaction ended
+ * @param aResolve State which UAC will enter if it decides to resolve URI
+ * @param aWaitResponse State which UAC enters if it decides to send
+ * request to the next ip-address.
+ */
+ void TransactionEndsWithoutFinalResponseL(TInt aReason,
+ const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse);
+
+ /**
+ * Remove message headers from CTransactionStore, so that in case a
+ * retransmission of a response is received, it will be dropped.
+ * This is required when ClientTransaction terminates before SIPSec has
+ * completed adding authentication parameters to the request.
+ */
+ void IgnoreResponseRetransmissionsL();
+
+ /**
+ * Cancel a pending asynchronous request issued to SIPSec.
+ */
+ void CancelSIPSecRequest();
+
+ /**
+ * Stores the remote target, replacing the possibly existing value.
+ *
+ * @param aRemoteTarget Remote target
+ */
+ void StoreRemoteTargetL(const CURIContainer& aRemoteTarget);
+
+ /**
+ * Handle the situation when resolving address has failed.
+ *
+ * @param aResolve State which UAC will enter if it decides to resolve
+ * another address
+ * @param aWaitResponse State which UAC enters if it decides to send
+ * request to the next ip-address.
+ */
+ void HandleResolvingFailure(const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse);
+
+ /**
+ * Returns the next hop address.
+ */
+ const TInetAddr& NextHopIP() const;
+
+protected:
+
+ CUserAgentClient(CUserAgentCreateParams& aParams,
+ MSipUriResolver& aResolver,
+ CSIPSec& aSIPSec,
+ TUint32 aCSeqNumber);
+
+ void ConstructL();
+
+ /**
+ * Fills new Via header with branch, to the aReq.
+ * Host part will be filled later by ConnectionMgr.
+ *
+ * @post aReq has one Via header
+ * @param aReq SIP request
+ * @param aBranch The branch value to put into the Via-header.
+ * If this is an empty string, a new branch is generated.
+ */
+ void FillNewViaL(CSIPRequest& aReq, RStringF aBranch) const;
+
+ /**
+ * Stores the Request-URI of aReq into iRequestUri member. If iRequestUri
+ * already had a value, it is replaced with the new value.
+ *
+ * @pre aReq.RequestURI() != NULL
+ * @post iRequestUri != NULL
+ *
+ * @param aReq SIP request
+ */
+ void StoreRequestUriL(CSIPRequest &aReq);
+
+ /**
+ * Updates the SIP request, so it can be re-sent after modifying it, or
+ * after obtaining another address.
+ * Current Via is removed and an updated Via with a new branch and
+ * transport to match the new remote address. CSeq is always updated.
+ *
+ * @pre iOutgoingMsg != NULL
+ * @post The request in iOutgoingMsg has new Via branch & CSeq number
+ */
+ void UpdateViaAndCSeqL() const;
+
+ /**
+ * Updates transaction object and some SIP message headers to the
+ * CTransactionStore.
+ *
+ * @param aReq SIP request from where a certain headers are updated to
+ * the store. If NULL, the headers are not updated.
+ */
+ void UpdateInfoToStoreL(CSIPRequest* aReq) const;
+
+ /**
+ * Sends the SIP request in the send buffer (CUserAgent::iOutgoingMsg) to
+ * network. If the request is ACK, it is sent directly with CTransmitter.
+ * Other requests are sent using CTransaction.
+ *
+ * @pre iOutgoingMsg != NULL
+ */
+ void SendRequestToNetworkL();
+
+ /**
+ * Passes the response to upper layer, except 100 response.
+ *
+ * @pre aResp != NULL, iFinalRespPassed == EFalse
+ *
+ * @param aResp SIP response, ownership is transferred
+ * @param aUserAgent If non-NULL, points to UserAgent which has aTimer
+ * @param aTimer If non-NULL, points to timer that will be stopped
+ */
+ void PassRespToTransactionOwnerL(CSIPResponse* aResp,
+ CUserAgent* aUserAgent=NULL,
+ CUserAgentTimer* aTimer=NULL);
+
+ /**
+ * Copies the currently used remote address and transport protocol from the
+ * given UAC (aSrc).
+ *
+ * @param aSrc UAC from which the address is copied
+ */
+ void CopyRemoteAddress(const CUserAgentClient& aSrc);
+
+ /**
+ * Copies the route set and remote target from the given UAC (aSrc).
+ *
+ * @pre iRouteSet = NULL
+ * @pre iRemoteTarget = NULL
+ * @pre aSrc.iRouteSet != NULL
+ * @pre aSrc.iRemoteTarget != NULL
+ * @param aSrc UAC from which the route set and remote target are copied
+ */
+ void CopyRouteSetAndRemoteTargetL(const CUserAgentClient& aSrc);
+
+ /**
+ * If UAC used a pre-configured route, but that failed, UAC tries to send
+ * the request to outbound proxy (if one has been configured).
+ *
+ * @param aResolve State which UAC will enter if it decides to try and
+ * resolve the outbound proxy.
+ * @return value ETrue if the request will be sent to next address,
+ * EFalse otherwise
+ */
+ TBool TryOutboundProxyL(const CUserAgentState& aResolve);
+
+ /**
+ * Gets the next hop URI.
+ *
+ * @pre iRouteSet != NULL
+ * @pre iRemoteTarget != NULL
+ * @param aUseResolvedProxy, ETrue if resolved address of registration
+ * @return CURIContainer& Next hop URI
+ */
+ CURIContainer& NextHopL(TBool aUseResolvedProxy = EFalse) const;
+
+ /**
+ * Resolves the next hop URI.
+ *
+ * @param aCheckSigComp ETrue if sigcomp support is checked, EFalse
+ * @param aUseResolvedProxy, ETrue if resolved address of registration
+ * otherwise.
+ */
+ void ResolveNextHopL(TBool aCheckSigComp,TBool aUseResolvedProxy = EFalse);
+
+ /**
+ * Makes sure the CTransmitter is ready to be used for an updated request.
+ *
+ * @param aNewTransactionId TransactionId that is given to the old
+ * transaction.
+ */
+ virtual void PrepareTxForNewRequestL(TTransactionId& aNewTransactionId) = 0;
+
+ /**
+ * Let SIPSec fill the security parameters into outgoing request.
+ *
+ * @pre iOutgoingMsg != NULL, iRemoteTarget != NULL
+ *
+ * @return value ETrue if successful, EFalse in case of error
+ */
+ TBool FillSecurityParamsL();
+
+protected: // Data
+
+ //SIP Security subsystem
+ CSIPSec& iSIPSec;
+
+ //CSeq sequence number to use in the SIP request, unless filled by upper
+ //layer.
+ TUint32 iCSeqNumber;
+
+ //Address where the request is sent
+ TInetAddr iRemoteAddr;
+
+ //ETrue if the transport of iRemoteAddr must not be changed from UDP
+ TBool iForceUDP;
+
+ //RegistrationId provided by the upper layer when it sent the request.
+ TRegistrationId iRegisterId;
+
+ //Route set associated with the SIP request, owned.
+ CRouteSet* iRouteSet;
+
+ //Remote target of the SIP request, owned.
+ CURIContainer* iRemoteTarget;
+
+ //Resolver subsystem
+ MSipUriResolver& iResolver;
+
+ //Results obtained from resolving an URI. Owned.
+ CResolvingResults* iResolvingResults;
+
+ //SIPSec Error
+ TInt iSipSecError;
+
+private:
+
+ /**
+ * Fill the transaction related headers to the SIP request, unless they
+ * have already been filled.
+ *
+ * @pre aReq must contain From header
+ * @pre iRemoteTarget != NULL
+ *
+ * @param aReq SIP request which is filled
+ */
+ void FillRequestL(CSIPRequest& aReq) const;
+
+ /**
+ * Fills Call-ID header into aReq
+ *
+ * @param aReq SIP request
+ */
+ void FillNewCallIdL(CSIPRequest& aReq) const;
+
+ /**
+ * Sets branch parameter to Via header.
+ *
+ * @post aVia Via header
+ * @param aBranch The branch value to put into the Via-header.
+ * If this is an empty string, a new branch is generated.
+ */
+ void SetBranchL(CSIPViaHeader& aVia, RStringF aBranch) const;
+
+ /**
+ * Processes the status of a SIPSec operation that can leave. If SIPSec
+ * reported an error, UAC is stopped and HandleSIPSecErrorL leaves.
+ *
+ * @param aError If leave occurred from the SIPSec operation, this is the
+ * leave code. Otherwise KErrNone.
+ * @leave If aError != KErrNone, HandleSIPSecErrorL will leave.
+ */
+ void HandleSIPSecErrorL(TInt aError);
+
+ /**
+ * Client transaction terminated because of a timeout.
+ * If the request was sent compressed, send it uncompressed to the same
+ * address. Otherwise if there are other addresses to try, they are
+ * used and resolved if necessary.
+ *
+ * @param aResolve UAC will enter this state if it decides to resolve URI.
+ * Resolving isn't done if UAC already has more resolving results to try.
+ * @param aWaitResponse UAC enters this state if it sends request again.
+ * @return value ETrue if UAC sends the request again or resolves another
+ * address. EFalse if UAC can't continue and will end.
+ */
+ TBool HandleTimeoutL(const CUserAgentState& aResolve,
+ const CUserAgentState& aWaitResponse);
+
+ /**
+ * Updates Request-URI and Route-headers of the request when reverting to
+ * try the outbound proxy.
+ *
+ * @param aProxy Outbound proxy URI
+ */
+ void UpdateRequestUriAndRouteL(const CURIContainer& aProxy);
+
+ /**
+ * Detach the current CTransaction object owned by the UserAgent. If the
+ * CTransaction has reached Terminated state, it is freed using DeleteMgr,
+ * otherwise it'll run independently of the UserAgent and when it enters
+ * Terminated state, it'll delete itself using DeleteMgr.
+ */
+ void DetachCurrentTransactionL();
+
+ /**
+ * Updates the SIP request and sends it using a new CTransaction object.
+ *
+ * The information of the current CTransaction object is removed from
+ * CTransactionStore, and the old CTransaction is detached from UserAgent.
+ * A new CTransaction instance is created and its information is added into
+ * the CTransactionStore and the SIP request is sent to the new
+ * CTransaction.
+ *
+ * @pre iOutgoingMsg != NULL
+ *
+ * @param aResolve UAC enters this state
+ */
+ void UpdateAndSendRequestL(const CUserAgentState& aWaitResponse);
+
+ /**
+ * Updates the SIP request, resolves the next hop URI and enters state
+ * aResolve.
+ *
+ * @pre iOutgoingMsg != NULL
+ *
+ * @param aCheckSigComp ETrue if sigcomp is checked from aUri
+ * @param aResolve UAC enters this state
+ */
+ void UpdateAndResolveL(TBool aCheckSigComp,
+ const CUserAgentState& aResolve);
+
+ /**
+ * Stop with a previously stored error code. If a stored response exists,
+ * pass it to upper layer before stopping.
+ */
+ void StopWithLastError();
+
+ /**
+ * If the next hop is an outbound proxy, this function returns the outbound
+ * proxy as descriptor. Otherwise returns an empty descriptor.
+ *
+ * @return const TDesC8& Outbound proxy, or empty descritor.
+ */
+ const TDesC8& ProxyL() const;
+
+ /**
+ * Determine if SIP messages should be handed to SIPSec or not.
+ * @return ETrue if SIP messages are given to SIPSec, EFalse otherwise
+ */
+ TBool UseSIPSec() const;
+
+private: // Data
+
+ // Indicates if UAC has passed a final response to MTransactionOwner
+ TBool iFinalRespPassed;
+
+ // Tells if any SIP response has been received.
+ TBool iResponseReceived;
+
+ // ETrue if UAC has attempted to resolve the outbound proxy, or sent a
+ // request to the outbound proxy. EFalse otherwise.
+ TBool iOutboundProxyHasBeenTried;
+
+ // Request-URI of the request, owned
+ CURIContainer* iRequestUri;
+
+ // Incremented each time a request and response are passed to SIPSec.
+ // Prevents infinite loop if the server always re-challenges.
+ TInt iSIPSecCounter;
+
+ // If transaction fails and UAC resolves the current URI again, the reason
+ // why transaction failed is stored here. If resolving the same URI fails,
+ // the stored error is passed to upper layer.
+ TInt iLastError;
+
+ // Normally EFalse. Temporarily set to ETrue to ignore SIPSec's callback
+ // when UAC cancels its pending SIPSec requests.
+ TBool iIgnoreSIPSecCallback;
+
+private: // For testing purposes
+
+#ifdef CPPUNIT_TEST
+ friend class CUserAgentClient_Test;
+ friend class CTransactionUser_Test;
+ friend class CNormalUAC_ResolveAddress_Test;
+ friend class CNormalUAC_WaitResponse_Test;
+ friend class CInviteUAC_ResolveAddress_Test;
+ friend class CInviteUAC_WaitResponse_Test;
+ friend class CInviteUAC_WaitAckFromApp_Test;
+ friend class CInviteUAC_ResolveAckAddress_Test;
+ friend class CInviteUAC_SendingAck_Test;
+ friend class CInviteUAC_Start_Test;
+ friend class CUserAgent_Test;
+ friend class CTransactionStore_Test;
+#endif
+
+ void __DbgTestInvariant() const;
+
+ };
+
+#endif // end of USERAGENTCLIENT_H
+
+// End of File