Class BOSHClient

java.lang.Object
org.igniterealtime.jbosh.BOSHClient

public final class BOSHClient extends Object
BOSH Client session instance. Each communication session with a remote connection manager is represented and handled by an instance of this class. This is the main entry point for client-side communications. To create a new session, a client configuration must first be created and then used to create a client instance:
 BOSHClientConfig cfg = BOSHClientConfig.Builder.create(
         "http://server:1234/httpbind", "jabber.org")
     .setFrom("user@jabber.org")
     .build();
 BOSHClient client = BOSHClient.create(cfg);
 
Additional client configuration options are available. See the BOSHClientConfig.Builder class for more information.

Once a BOSHClient instance has been created, communication with the remote connection manager can begin. No attempt will be made to establish a connection to the connection manager until the first call is made to the send(ComposableBody) method. Note that it is possible to send an empty body to cause an immediate connection attempt to the connection manager. Sending an empty message would look like the following:

 client.send(ComposableBody.builder().build());
 
For more information on creating body messages with content, see the ComposableBody.Builder class documentation.

Once a session has been successfully started, the client instance can be used to send arbitrary payload data. All aspects of the BOSH protocol involving setting and processing attributes in the BOSH namespace will be handled by the client code transparently and behind the scenes. The user of the client instance can therefore concentrate entirely on the content of the message payload, leaving the semantics of the BOSH protocol to the client implementation.

To be notified of incoming messages from the remote connection manager, a BOSHClientResponseListener should be added to the client instance. All incoming messages will be published to all response listeners as they arrive and are processed. As with the transmission of payload data via the send(ComposableBody) method, there is no need to worry about handling of the BOSH attributes, since this is handled behind the scenes.

If the connection to the remote connection manager is terminated (either explicitly or due to a terminal condition of some sort), all connection listeners will be notified. After the connection has been closed, the client instance is considered dead and a new one must be created in order to resume communications with the remote server.

Instances of this class are thread-safe.

See Also:
  • Field Details

    • LOG

      private static final Logger LOG
      Logger.
    • TERMINATE

      private static final String TERMINATE
      Value of the 'type' attribute used for session termination.
      See Also:
    • ERROR

      private static final String ERROR
      Value of the 'type' attribute used for recoverable errors.
      See Also:
    • INTERRUPTED

      private static final String INTERRUPTED
      Message to use for interrupted exceptions.
      See Also:
    • UNHANDLED

      private static final String UNHANDLED
      Message used for unhandled exceptions.
      See Also:
    • NULL_LISTENER

      private static final String NULL_LISTENER
      Message used whena null listener is detected.
      See Also:
    • DEFAULT_EMPTY_REQUEST_DELAY

      private static final int DEFAULT_EMPTY_REQUEST_DELAY
      Default empty request delay.
      See Also:
    • EMPTY_REQUEST_DELAY

      private static final int EMPTY_REQUEST_DELAY
      Amount of time to wait before sending an empty request, in milliseconds.
    • DEFAULT_PAUSE_MARGIN

      private static final int DEFAULT_PAUSE_MARGIN
      Default value for the pause margin.
      See Also:
    • PAUSE_MARGIN

      private static final int PAUSE_MARGIN
      The amount of time in milliseconds which will be reserved as a safety margin when scheduling empty requests against a maxpause value. This should give us enough time to build the message and transport it to the remote host.
    • ASSERTIONS

      private static final boolean ASSERTIONS
      Flag indicating whether or not we want to perform assertions.
    • connListeners

      private final Set<BOSHClientConnListener> connListeners
      Connection listeners.
    • requestListeners

      private final Set<BOSHClientRequestListener> requestListeners
      Request listeners.
    • responseListeners

      private final Set<BOSHClientResponseListener> responseListeners
      Response listeners.
    • lock

      private final ReentrantLock lock
      Lock instance.
    • notEmpty

      private final Condition notEmpty
      Condition indicating that there are messages to be exchanged.
    • notFull

      private final Condition notFull
      Condition indicating that there are available slots for sending messages.
    • drained

      private final Condition drained
      Condition indicating that there are no outstanding connections.
    • cfg

      private final BOSHClientConfig cfg
      Session configuration.
    • procRunnable

      private final Runnable procRunnable
      Processor thread runnable instance.
    • emptyRequestRunnable

      private final Runnable emptyRequestRunnable
      Processor thread runnable instance.
    • httpSender

      private final HTTPSender httpSender
      HTTPSender instance.
    • exchInterceptor

      private final AtomicReference<BOSHClient.ExchangeInterceptor> exchInterceptor
      Storage for test hook implementation.
    • requestIDSeq

      private final RequestIDSequence requestIDSeq
      Request ID sequence to use for the session.
    • schedExec

      private final ScheduledExecutorService schedExec
      ScheduledExcecutor to use for deferred tasks.
    • procThread

      private Thread procThread
      Thread which is used to process responses from the connection manager. Becomes null when session is terminated.
    • emptyRequestFuture

      private ScheduledFuture emptyRequestFuture
      Future for sending a deferred empty request, if needed.
    • cmParams

      private CMSessionParams cmParams
      Connection Manager session parameters. Only available when in a connected state.
    • exchanges

      private Queue<HTTPExchange> exchanges
      List of active/outstanding requests.
    • pendingResponseAcks

      private SortedSet<Long> pendingResponseAcks
      Set of RIDs which have been received, for the purpose of sending response acknowledgements.
    • responseAck

      private Long responseAck
      The highest RID that we've already received a response for. This value is used to implement response acks.
    • pendingRequestAcks

      private List<ComposableBody> pendingRequestAcks
      List of requests which have been made but not yet acknowledged. This list remains unpopulated if the CM is not acking requests.
  • Constructor Details

    • BOSHClient

      private BOSHClient(BOSHClientConfig sessCfg)
      Prevent direct construction.
  • Method Details

    • create

      public static BOSHClient create(BOSHClientConfig clientCfg)
      Create a new BOSH client session using the client configuration information provided.
      Parameters:
      clientCfg - session configuration
      Returns:
      BOSH session instance
    • getBOSHClientConfig

      public BOSHClientConfig getBOSHClientConfig()
      Get the client configuration that was used to create this client instance.
      Returns:
      client configuration
    • addBOSHClientConnListener

      public void addBOSHClientConnListener(BOSHClientConnListener listener)
      Adds a connection listener to the session.
      Parameters:
      listener - connection listener to add, if not already added
    • removeBOSHClientConnListener

      public void removeBOSHClientConnListener(BOSHClientConnListener listener)
      Removes a connection listener from the session.
      Parameters:
      listener - connection listener to remove, if previously added
    • addBOSHClientRequestListener

      public void addBOSHClientRequestListener(BOSHClientRequestListener listener)
      Adds a request message listener to the session.
      Parameters:
      listener - request listener to add, if not already added
    • removeBOSHClientRequestListener

      public void removeBOSHClientRequestListener(BOSHClientRequestListener listener)
      Removes a request message listener from the session, if previously added.
      Parameters:
      listener - instance to remove
    • addBOSHClientResponseListener

      public void addBOSHClientResponseListener(BOSHClientResponseListener listener)
      Adds a response message listener to the session.
      Parameters:
      listener - response listener to add, if not already added
    • removeBOSHClientResponseListener

      public void removeBOSHClientResponseListener(BOSHClientResponseListener listener)
      Removes a response message listener from the session, if previously added.
      Parameters:
      listener - instance to remove
    • send

      public void send(ComposableBody body) throws BOSHException
      Send the provided message data to the remote connection manager. The provided message body does not need to have any BOSH-specific attribute information set. It only needs to contain the actual message payload that should be delivered to the remote server.

      The first call to this method will result in a connection attempt to the remote connection manager. Subsequent calls to this method will block until the underlying session state allows for the message to be transmitted. In certain scenarios - such as when the maximum number of outbound connections has been reached - calls to this method will block for short periods of time.

      Parameters:
      body - message data to send to remote server
      Throws:
      BOSHException - on message transmission failure
    • pause

      public boolean pause()
      Attempt to pause the current session. When supported by the remote connection manager, pausing the session will result in the connection manager closing out all outstanding requests (including the pause request) and increases the inactivity timeout of the session. The exact value of the temporary timeout is dependent upon the connection manager. This method should be used if a client encounters an exceptional temporary situation during which it will be unable to send requests to the connection manager for a period of time greater than the maximum inactivity period. The session will revert back to it's normal, unpaused state when the client sends it's next message.
      Returns:
      true if the connection manager supports session pausing, false if the connection manager does not support session pausing or if the session has not yet been established
    • disconnect

      public void disconnect() throws BOSHException
      End the BOSH session by disconnecting from the remote BOSH connection manager.
      Throws:
      BOSHException - when termination message cannot be sent
    • disconnect

      public void disconnect(ComposableBody msg) throws BOSHException
      End the BOSH session by disconnecting from the remote BOSH connection manager, sending the provided content in the final connection termination message.
      Parameters:
      msg - final message to send
      Throws:
      BOSHException - when termination message cannot be sent
    • close

      public void close()
      Forcibly close this client session instance. The preferred mechanism to close the connection is to send a disconnect message and wait for organic termination. Calling this method simply shuts down the local session without sending a termination message, releasing all resources associated with the session.
    • getCMSessionParams

      CMSessionParams getCMSessionParams()
      Get the current CM session params.
      Returns:
      current session params, or null
    • drain

      void drain()
      Wait until no more messages are waiting to be processed.
    • setExchangeInterceptor

      void setExchangeInterceptor(BOSHClient.ExchangeInterceptor interceptor)
      Test method used to forcibly discard next exchange.
      Parameters:
      interceptor - exchange interceptor
    • init

      private void init()
      Initialize the session. This initializes the underlying HTTP transport implementation and starts the receive thread.
    • dispose

      private void dispose(Throwable cause)
      Destroy this session.
      Parameters:
      cause - the reason for the session termination, or null for normal termination
    • isPause

      private static boolean isPause(AbstractBody msg)
      Determines if the message body specified indicates a request to pause the session.
      Parameters:
      msg - message to evaluate
      Returns:
      true if the message is a pause request, false otherwise
    • isTermination

      private static boolean isTermination(AbstractBody msg)
      Determines if the message body specified indicates a termination of the session.
      Parameters:
      msg - message to evaluate
      Returns:
      true if the message is a session termination, false otherwise
    • getTerminalBindingCondition

      private TerminalBindingCondition getTerminalBindingCondition(int respCode, AbstractBody respBody)
      Evaluates the HTTP response code and response message and returns the terminal binding condition that it describes, if any.
      Parameters:
      respCode - HTTP response code
      respBody - response body
      Returns:
      terminal binding condition, or null if not a terminal binding condition message
    • isImmediatelySendable

      private boolean isImmediatelySendable(AbstractBody msg)
      Determines if the message specified is immediately sendable or if it needs to block until the session state changes.
      Parameters:
      msg - message to evaluate
      Returns:
      true if the message can be immediately sent, false otherwise
    • isWorking

      private boolean isWorking()
      Determines whether or not the session is still active.
      Returns:
      true if it is, false otherwise
    • blockUntilSendable

      private void blockUntilSendable(AbstractBody msg)
      Blocks until either the message provided becomes immediately sendable or until the session is terminated.
      Parameters:
      msg - message to evaluate
    • applySessionCreationRequest

      private ComposableBody applySessionCreationRequest(long rid, ComposableBody orig) throws BOSHException
      Modifies the specified body message such that it becomes a new BOSH session creation request.
      Parameters:
      rid - request ID to use
      orig - original body to modify
      Returns:
      modified message which acts as a session creation request
      Throws:
      BOSHException
    • applyRoute

      private void applyRoute(ComposableBody.Builder builder)
      Applies routing information to the request message who's builder has been provided.
      Parameters:
      builder - builder instance to add routing information to
    • applyFrom

      private void applyFrom(ComposableBody.Builder builder)
      Applies the local station ID information to the request message who's builder has been provided.
      Parameters:
      builder - builder instance to add station ID information to
    • applySessionData

      private ComposableBody applySessionData(long rid, ComposableBody orig) throws BOSHException
      Applies existing session data to the outbound request, returning the modified request. This method assumes the lock is currently held.
      Parameters:
      rid - request ID to use
      orig - original/raw request
      Returns:
      modified request with session information applied
      Throws:
      BOSHException
    • applyResponseAcknowledgement

      private void applyResponseAcknowledgement(ComposableBody.Builder builder, long rid)
      Sets the 'ack' attribute of the request to the value of the highest 'rid' of a request for which it has already received a response in the case where it has also received all responses associated with lower 'rid' values. The only exception is that, after its session creation request, the client SHOULD NOT include an 'ack' attribute in any request if it has received responses to all its previous requests.
      Parameters:
      builder - message builder
      rid - current request RID
    • processMessages

      private void processMessages()
      While we are "connected", process received responses. This method is run in the processing thread.
    • nextExchange

      private HTTPExchange nextExchange()
      Get the next message exchange to process, blocking until one becomes available if nothing is already waiting for processing.
      Returns:
      next available exchange to process, or null if no exchanges are immediately available
    • processExchange

      private void processExchange(HTTPExchange exch)
      Process the next, provided exchange. This is the main processing method of the receive thread.
      Parameters:
      exch - message exchange to process
    • clearEmptyRequest

      private void clearEmptyRequest()
      Clears any scheduled empty requests.
    • getDefaultEmptyRequestDelay

      private long getDefaultEmptyRequestDelay()
      Calculates the default empty request delay/interval to use for the active session.
      Returns:
      delay in milliseconds
    • scheduleEmptyRequest

      private void scheduleEmptyRequest(long delay)
      Schedule an empty request to be sent if no other requests are sent in a reasonable amount of time.
    • sendEmptyRequest

      private void sendEmptyRequest()
      Sends an empty request to maintain session requirements. If a request is sent within a reasonable time window, the empty request transmission will be cancelled.
    • assertLocked

      private void assertLocked()
      Assert that the internal lock is held.
    • assertUnlocked

      private void assertUnlocked()
      Assert that the internal lock is *not* held.
    • checkForTerminalBindingConditions

      private void checkForTerminalBindingConditions(AbstractBody body, int code) throws BOSHException
      Checks to see if the response indicates a terminal binding condition (as per XEP-0124 section 17). If it does, an exception is thrown.
      Parameters:
      body - response body to evaluate
      code - HTTP response code
      Throws:
      BOSHException - if a terminal binding condition is detected
    • isRecoverableBindingCondition

      private static boolean isRecoverableBindingCondition(AbstractBody resp)
      Determines whether or not the response indicates a recoverable binding condition (as per XEP-0124 section 17).
      Parameters:
      resp - response body
      Returns:
      true if it does, false otherwise
    • processPauseRequest

      private long processPauseRequest(AbstractBody req)
      Process the request to determine if the empty request delay can be determined by looking to see if the request is a pause request. If it can, the request's delay is returned, otherwise the default delay is returned.
      Returns:
      delay in milliseconds that should elapse prior to an empty message being sent
    • processRequestAcknowledgements

      private void processRequestAcknowledgements(AbstractBody req, AbstractBody resp)
      Check the response for request acknowledgements and take appropriate action. This method assumes the lock is currently held.
      Parameters:
      req - request
      resp - response
    • processResponseAcknowledgementData

      private void processResponseAcknowledgementData(AbstractBody req)
      Process the response in order to update the response acknowlegement data. This method assumes the lock is currently held.
      Parameters:
      req - request
    • processResponseAcknowledgementReport

      private HTTPExchange processResponseAcknowledgementReport(AbstractBody resp) throws BOSHException
      Process the response in order to check for and respond to any potential ack reports. This method assumes the lock is currently held.
      Parameters:
      resp - response
      Returns:
      exchange to transmit if a resend is to be performed, or null if no resend is necessary
      Throws:
      BOSHException - when a a retry is needed but cannot be performed
    • fireRequestSent

      private void fireRequestSent(AbstractBody request)
      Notifies all request listeners that the specified request is being sent.
      Parameters:
      request - request being sent
    • fireResponseReceived

      private void fireResponseReceived(AbstractBody response)
      Notifies all response listeners that the specified response has been received.
      Parameters:
      response - response received
    • fireConnectionEstablished

      private void fireConnectionEstablished()
      Notifies all connection listeners that the session has been successfully established.
    • fireConnectionClosed

      private void fireConnectionClosed()
      Notifies all connection listeners that the session has been terminated normally.
    • fireConnectionClosedOnError

      private void fireConnectionClosedOnError(Throwable cause)
      Notifies all connection listeners that the session has been terminated due to the exceptional condition provided.
      Parameters:
      cause - cause of the termination