Interface SipSession


  • public interface SipSession
    The SipSession is the main activity object in the EasySIP API. It roughly corresponds to a SIP dialog but is also used for out-of-dialog requests. This is to reduce the number of activity types that an SBB needs to create and stay attached to, simplifying SBB code. The lifecycle of a SipSession activity depends on how it is used.

    UAC (User Agent Client) mode

    UAC SipSession activities are created using the SipFactory.createRequest() methods. The OutgoingSipRequest returned by these methods belongs to a new UAC SipSession. The SBB must attach to the SipSession's ActivityContextInterface in order to receive responses. After the request is sent, the SipSession lifecycle proceeds as follows:

    If an error response arrives, the SipSession does not end. It may be reused to create another initial request with the same call-id, tag etc. This is to support the case where a redirect response or authentication response is received, so the SBB can easily create a new request with the same parameters and any additional info required, and re-send. If the SBB really does want the SipSession to end at this point, it must call invalidate().

    If a successful final response (2xx) arrives, and the initial request was not a dialog-creating request, then the SipSession activity ends automatically. Out of dialog requests are handled in this way, and the SipSession activity represents a single SIP client transaction.
    If the initial request was dialog-creating (currently INVITE and SUBSCRIBE), then the SipSession stays alive. The SipSession now represents a "confirmed" SIP dialog between the UAC SBB and the peer UAS, and the SBB may create and send more in-dialog requests using the SipSession, and will also receive in-dialog requests from the peer, as long as the SBB stays attached.

    When the SipSession sends or receives a request that ends the dialog (a BYE, or NOTIFY with the "Subsciption-State: terminated" header), the SipSession ends after the response to that request is sent or received. The RA will ensure that activites are ended even if the SBB does not process the request.

    UAS (User Agent Server) mode

    UAS SipSessions are created automatically by the RA when an incoming initial request is received (a request that does not belong to an existing dialog, ie. no To-tag specified). An IncomingSipRequest event is fired on the SipSession activity.

    If the UAS SBB sends an error (3xx-6xx) response, the SipSession activity ends automatically. If the request was not a dialog-creating request, the SipSession also ends when a 2xx response is sent. In this way it behaves like a SIP server transaction. For dialog-creating requests, sending a 2xx response means the SipSession activity stays alive and now represents a "confirmed" SIP dialog between the UAS SBB and the UAC peer. Similarly, sending a 101-199 response will create an "early" dialog, which transitions to "confirmed" when the 2xx response is sent. Now the SBB may create and send more in-dialog requests using the SipSession, and will also receive in-dialog requests from the peer, as long as the SBB stays attached.

    When the SipSession sends or receives a request that ends the dialog (a BYE, or NOTIFY with the "Subsciption-State: terminated" header), the SipSession ends after the response to that request is sent or received. The RA will ensure that activites are ended even if the SBB does not process the request.

    If the UAS SBB wishes to proxy the request, it must call IncomingSipRequest.getProxy() before generating a response itself. If the SBB generates it's own response, the RA assumes that the SBB is behaving like a UAS (ie. the endpoint of a dialog) and will not allow the request to be proxied. An IllegalStateException will be thrown if the UAS SBB attempts to obtain the proxy after it has already sent a dialog-creating response. If a Proxy is created, the SipSession continues in Proxy mode, explained below.

    Proxy mode

    A SipSession enters Proxy mode after an SBB calls IncomingSipRequest.getProxy() on the initial request. If the initial request was not a dialog-creating request, the SipSession ends when the final response is forwarded by the proxy. If the initial request was dialog-creating, the SipSession ends if an error response is forwarded by the proxy. If a 2xx response is received for a dialog-creating request, the SipSession represents the confirmed SIP dialog between the 2 SIP endpoints. The proxy SBB will then receive all subsequent in-dialog requests from either endpoint, as long as it is attached to the SipSession activity. In-dialog requests will be forwarded automatically (unless the SBB sends it's own response to an in-dialog request - see the Proxy documentation for details).

    A proxy mode SipSession may not be used for initiating in-dialog requests (createRequest(String) will throw an \IllegalStateException), since this is not the role of a proxy. A proxy may only forward requests from the SIP endpoints, but can modify these requests as they pass through, or reject them.

    As before, when a dialog-ending request is received from either party, the SipSession ends when the corresponding response is received.

    Forcibly ending a SipSession

    SipSessions may be ended at any time by calling invalidate(). This just removes the activity state from the SLEE and RA, it does not cause any SIP messages to be sent. If the RA receives subsequent requests for an unknown SipSession, these will be automatically rejected with a "481 (Call or Transaction Does Not Exist)" response.

    Retransmit Behaviour

    UAS or UAC SipSessions will automatically perform retransmits of the INVITE 2xx responses and ACKs, respectively. The SBB does not need to do anything else after sending the first 2xx or ACK. This also applies to re-INVITEs on an existing SipSession. For Proxy SipSessions, no special retransmit handling is performed since this is the responsibility of the SIP endpoints. All 2xx responses and ACKs will be passed through so that the SIP endpoints can deal with them.
    • Method Detail

      • getId

        String getId()
        Returns a string containing the unique identifier assigned to this session. The value is assigned by the RA and is implementation-specific, and does not necessarily to correspond to the dialog ID.
        Returns:
        a string specifying the unique identifier assigned to this session
      • invalidate

        void invalidate()
        Ends this SipSession activity. Subsequent operations on this session will fail with IllegalStateException.
      • getCallId

        String getCallId()
      • getLocalParty

        Address getLocalParty()
      • getRemoteParty

        Address getRemoteParty()
      • createRequest

        OutgoingSipRequest createRequest​(IncomingSipRequest original)
        Create a new request on this session, with all headers and content copied from another request. Headers that are derived from the dialog state (Call-Id, CSeq, Route, From, To and the request-URI) are not copied, they are set from the dialog state as usual. This is a convenience method so that B2BUAs can forward in-dialog requests easily.
        Parameters:
        original - the original request, will usually have been received on a different SipSession.
        Returns:
        a new request on this session
        Since:
        EasySIP 1.0 - no equivalent in SIP Servlet API
      • createForkedNotify

        OutgoingSipRequest createForkedNotify​(IncomingSipRequest notify)
        Creates a new outgoing NOTIFY request and a new SipSession, for forwarding forked NOTIFY requests upstream.

        This is a convenience method so that B2BUAs handling several UAC SipSessions created by a downstream element forking an initial SUBSCRIBE can easily create the corresponding UAS SipSessions. The new forked UAS session can be obtained by calling SipMessage.getSession() on the returned OutgoingSipRequest.

        The caller sends the new NOTIFY upstream by calling its OutgoingSipRequest.send() method.

        Parameters:
        notify - a forked NOTIFY request received on a UAC SipSession
        Returns:
        a new OutgoingSipRequest copied from the incoming request, but with the relevant headers set from the dialog state of the new SipSession. The Call-Id and remote tag will are copied from the UAS SipSession that was created by the initial SUBSCRIBE, and the local tag will be taken from the from-tag of the incoming NOTIFY.
        Throws:
        IllegalArgumentException - if the request was not a forked NOTIFY request, see IncomingSipRequest.isForked()
        Since:
        EasySIP RA Type 1.4
      • getInitialRequest

        SipRequest getInitialRequest()
        Get the incoming or outgoing request that initiated this session.
        Since:
        EasySIP 1.0 - not in SIP Servlet API
      • getSipFactory

        SipFactory getSipFactory()
        Get the SipFactory that created this SipSession.
        Since:
        EasySIP 1.0 - no equivalent in SIP Servlet API
      • sendCancel

        void sendCancel()
                 throws SipException
        Convenience method to send a CANCEL request for the current outgoing INVITE request on this session. If there is no outgoing INVITE request (client transaction) in progress, this method throws an exception.
        Throws:
        SipException - if unable to create the cancel request
        Since:
        EasySIP 1.2
      • sendCancel

        void sendCancel​(SipRequest cancel)
                 throws SipException
        Convenience method to send a CANCEL request for the current outgoing INVITE request on this session, copying any Reason headers from another CANCEL. If there is no outgoing INVITE request (client transaction) in progress, this method throws an exception.
        Parameters:
        cancel - a CANCEL request that triggered sending a CANCEL on this session. Any Reason headers from this CANCEL are copied to the outgoing CANCEL.
        Throws:
        SipException - if unable to create the cancel request
        Since:
        EasySIP 1.7
      • sendCancel

        void sendCancel​(Parameterable... headers)
                 throws SipException
        Convenience method to send a CANCEL request for the current outgoing INVITE request on this session, with the given Reason headers. If there is no outgoing INVITE request (client transaction) in progress, this method throws an exception.
        Parameters:
        headers - zero or more Parameterable values that will be added to the outgoing CANCEL as Reason headers.
        Throws:
        SipException - if unable to create the cancel request
        Since:
        EasySIP 1.7
      • setAttribute

        void setAttribute​(String name,
                          Object value)
        Binds an object to an attribute name in this session
        Parameters:
        name - a string specifying the name of the object, may not be null
        value - the object to be bound
        Throws:
        NullPointerException - if name or value are null
      • getAttribute

        Object getAttribute​(String name)
        Returns the object bound to the specified attribute name in this session
        Parameters:
        name - the attribute name, may not be null
        Returns:
        the object bound to the attribute name, or null if there is no object with that name
        Throws:
        NullPointerException - if name is null
      • removeAttribute

        void removeAttribute​(String name)
        Removes the named object from this session. If no object is bound to the name, this method does nothing.
        Parameters:
        name - the attribute name, may not be null
        Throws:
        NullPointerException - if name is null
      • getAttributeNames

        Iterable<String> getAttributeNames()
        Returns all attribute names that have been bound to objects in this session. The order of attribute names is undefined. Note the returned collection is a snapshot of the current attribute names, any changes to the underlying attributes will not propagate to the collection.
        Returns:
        a read-only collection of strings, empty if there were no attributes stored in the session.
      • setEndImmediately

        void setEndImmediately​(boolean endImmediately)
        Specify whether this session activity will end immediately after a dialog-ending message is sent or received (e.g. BYE). The default value is true. If set to false, the application must end the session explicitly using invalidate(). This gives the application a chance to keep using session attributes before the activity is finally ended in the SLEE. If the application does not call invalidate() itself, the session activity will be ended automatically by RA's next query-liveness processing, which occurs when the activity has been idle for some time, typically 5 minutes.
        Parameters:
        endImmediately - set to false to delay the automatic ending of this activity.
        Since:
        EasySIP 1.4
      • isEndImmediately

        boolean isEndImmediately()
        Returns the current value of this session's endImmediately flag.
        Returns:
        the session's endImmediately flag
        Since:
        EasySIP 1.4
      • setLocalContactAddress

        void setLocalContactAddress​(Address address)
        Enforces the policy where specified local Contact header is used for all outgoing target refresh responses and requests. This method should only be used by an application in role of UAS or UAC. If a target refresh message with a new Contact header value is sent on this session, the new Contact header value will be discarded and replaced with the value supplied to this method. When a forked outgoing response is created UAS session local Contact header will not be copied into the new session spawned by the forked response. When a forking incoming response creates a new UAC session local Contact header will be copied into the new session spawned by the forking response. Equivalent to calling setLocalContactAddress(address, false).
        Parameters:
        address - local Contact address
        Throws:
        NullPointerException - if address is null
        Since:
        EasySIP 1.4
      • setLocalContactAddress

        void setLocalContactAddress​(Address address,
                                    boolean enablePassthrough)
        Enforces the policy where specified local Contact header is used for all outgoing target refresh responses and requests. This method should only be used by an application in role of UAS or UAC. The value of enablePassthrough determines whether the local Contact header will automatically update when a target refresh message with a new Contact header is sent on this session. If true, the local Contact for the session will automatically be updated to match the new message (bear in mind that includes any messages sent immediately after calling this method). If false, the local Contact will not change, and will override the Contact header value in the message. When a forked outgoing response is created UAS session local Contact header will not be copied into the new session spawned by the forked response. When a forking incoming response creates a new UAC session local Contact header will be copied into the new session spawned by the forking response.
        Parameters:
        address - local Contact address
        enablePassthrough - if true, the Contact header on any target refresh sent on this session after calling this method will automatically replace the provided local Contact address.
        Throws:
        NullPointerException - if address is null
        Since:
        EasySIP 1.4
      • getLocalContactAddress

        Address getLocalContactAddress()
        Gets the current address that will be used for the Contact header on all target refresh messages that are sent on this session. Will return null if that address has not yet been determined, which will be the case if a target refresh message has not already been sent on this session, and a service has not otherwise specified an address to use. The returned address is a clone of the original, so changes to it will not affect the value held by the SipSession.
        Returns:
        a copy of the current local Contact header address
      • getPendingIncomingRequest

        IncomingSipRequest getPendingIncomingRequest​(long cseq)
        Retrieve a pending incoming request received on this session. A pending incoming request represents an active SIP server transaction on this session, for which no final response has been sent yet. This may include the session's initial request, if it was an incoming request.
        Parameters:
        cseq - the sequence number of the request.
        Returns:
        the matching pending IncomingSipRequest, or null if no such request was found.
        Since:
        EasySIP 1.4
      • getPendingOutgoingRequest

        OutgoingSipRequest getPendingOutgoingRequest​(long cseq)
        Retrieve a pending outgoing request sent on this session. A pending outgoing request represents an active SIP client transaction on this session, for which no final response has been received yet. This may include the session's initial request, if it was an outgoing request.
        Parameters:
        cseq - the sequence number of the request.
        Returns:
        the matching pending OutgoingSipRequest, or null if no such request was found.
        Since:
        EasySIP 1.4
      • getPendingIncomingRequests

        Iterable<IncomingSipRequest> getPendingIncomingRequests()
        Retrieve all pending incoming requests on this session. A pending incoming request represents an active SIP server transaction on this session, for which no final response has been sent yet. This may include the session's initial request, if it was an incoming request.
        Returns:
        a read-only sequence of IncomingSipRequests, empty if there are currently no pending requests.
        Since:
        EasySIP 1.4
      • getPendingOutgoingRequests

        Iterable<OutgoingSipRequest> getPendingOutgoingRequests()
        Retrieve all pending outgoing requests on this session. A pending outgoing request represents an active SIP client transaction on this session, for which no final response has been received yet. This may include the session's initial request, if it was an outgoing request.
        Returns:
        a read-only sequence of OutgoingSipRequests, empty if there are currently no pending requests.
        Since:
        EasySIP 1.4
      • getPeerDialogID

        DialogID getPeerDialogID()
        The peered SIP session is the session corresponding to this one on the other side of a B2BUA. Usually this Dialog ID is used when translating the Replaces/Refer-To headers that appear in otherwise unrelated SIP sessions.
        Returns:
        The dialog ID of the peered session.
      • setPeerDialogID

        void setPeerDialogID​(DialogID peerDialogID)
        The peered SIP session is the session corresponding to this one on the other side of a B2BUA. Usually this Dialog ID is used when translating the Replaces/Refer-To headers that appear in otherwise unrelated SIP sessions.
        Parameters:
        peerDialogID - The dialog ID of the peered session.
      • startReplicating

        void startReplicating()
        Instructs the SIS to begin replicating this session's state.

        If replication is disabled in the SIS, or the session is already replicating, this method does nothing.

        Otherwise if replication is enabled in the SIS, then this method instructs the SIS to begin replicating the session state.

      • isInviteTerminated

        boolean isInviteTerminated()
      • isSubscriptionsTerminated

        boolean isSubscriptionsTerminated()