Package org.igniterealtime.jbosh
Class BOSHClient
java.lang.Object
org.igniterealtime.jbosh.BOSHClient
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:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static class
Class used in testing to dynamically manipulate received exchanges at test runtime. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final boolean
Flag indicating whether or not we want to perform assertions.private final BOSHClientConfig
Session configuration.private CMSessionParams
Connection Manager session parameters.private final Set
<BOSHClientConnListener> Connection listeners.private static final int
Default empty request delay.private static final int
Default value for the pause margin.private final Condition
Condition indicating that there are no outstanding connections.private static final int
Amount of time to wait before sending an empty request, in milliseconds.private ScheduledFuture
Future for sending a deferred empty request, if needed.private final Runnable
Processor thread runnable instance.private static final String
Value of the 'type' attribute used for recoverable errors.private Queue
<HTTPExchange> List of active/outstanding requests.private final AtomicReference
<BOSHClient.ExchangeInterceptor> Storage for test hook implementation.private final HTTPSender
HTTPSender instance.private static final String
Message to use for interrupted exceptions.private final ReentrantLock
Lock instance.private static final Logger
Logger.private final Condition
Condition indicating that there are messages to be exchanged.private final Condition
Condition indicating that there are available slots for sending messages.private static final String
Message used whena null listener is detected.private static final int
The amount of time in milliseconds which will be reserved as a safety margin when scheduling empty requests against a maxpause value.private List
<ComposableBody> List of requests which have been made but not yet acknowledged.Set of RIDs which have been received, for the purpose of sending response acknowledgements.private final Runnable
Processor thread runnable instance.private Thread
Thread which is used to process responses from the connection manager.private final RequestIDSequence
Request ID sequence to use for the session.private final Set
<BOSHClientRequestListener> Request listeners.private Long
The highest RID that we've already received a response for.private final Set
<BOSHClientResponseListener> Response listeners.private final ScheduledExecutorService
ScheduledExcecutor to use for deferred tasks.private static final String
Value of the 'type' attribute used for session termination.private static final String
Message used for unhandled exceptions. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprivate
BOSHClient
(BOSHClientConfig sessCfg) Prevent direct construction. -
Method Summary
Modifier and TypeMethodDescriptionvoid
Adds a connection listener to the session.void
Adds a request message listener to the session.void
Adds a response message listener to the session.private void
applyFrom
(ComposableBody.Builder builder) Applies the local station ID information to the request message who's builder has been provided.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.private void
applyRoute
(ComposableBody.Builder builder) Applies routing information to the request message who's builder has been provided.private ComposableBody
applySessionCreationRequest
(long rid, ComposableBody orig) Modifies the specified body message such that it becomes a new BOSH session creation request.private ComposableBody
applySessionData
(long rid, ComposableBody orig) Applies existing session data to the outbound request, returning the modified request.private void
Assert that the internal lock is held.private void
Assert that the internal lock is *not* held.private void
Blocks until either the message provided becomes immediately sendable or until the session is terminated.private void
checkForTerminalBindingConditions
(AbstractBody body, int code) Checks to see if the response indicates a terminal binding condition (as per XEP-0124 section 17).private void
Clears any scheduled empty requests.void
close()
Forcibly close this client session instance.static BOSHClient
create
(BOSHClientConfig clientCfg) Create a new BOSH client session using the client configuration information provided.void
End the BOSH session by disconnecting from the remote BOSH connection manager.void
disconnect
(ComposableBody msg) End the BOSH session by disconnecting from the remote BOSH connection manager, sending the provided content in the final connection termination message.private void
Destroy this session.(package private) void
drain()
Wait until no more messages are waiting to be processed.private void
Notifies all connection listeners that the session has been terminated normally.private void
Notifies all connection listeners that the session has been terminated due to the exceptional condition provided.private void
Notifies all connection listeners that the session has been successfully established.private void
fireRequestSent
(AbstractBody request) Notifies all request listeners that the specified request is being sent.private void
fireResponseReceived
(AbstractBody response) Notifies all response listeners that the specified response has been received.Get the client configuration that was used to create this client instance.(package private) CMSessionParams
Get the current CM session params.private long
Calculates the default empty request delay/interval to use for the active session.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.private void
init()
Initialize the session.private boolean
Determines if the message specified is immediately sendable or if it needs to block until the session state changes.private static boolean
isPause
(AbstractBody msg) Determines if the message body specified indicates a request to pause the session.private static boolean
Determines whether or not the response indicates a recoverable binding condition (as per XEP-0124 section 17).private static boolean
Determines if the message body specified indicates a termination of the session.private boolean
Determines whether or not the session is still active.private HTTPExchange
Get the next message exchange to process, blocking until one becomes available if nothing is already waiting for processing.boolean
pause()
Attempt to pause the current session.private void
processExchange
(HTTPExchange exch) Process the next, provided exchange.private void
While we are "connected", process received responses.private long
Process the request to determine if the empty request delay can be determined by looking to see if the request is a pause request.private void
Check the response for request acknowledgements and take appropriate action.private void
Process the response in order to update the response acknowlegement data.private HTTPExchange
Process the response in order to check for and respond to any potential ack reports.void
Removes a connection listener from the session.void
Removes a request message listener from the session, if previously added.void
Removes a response message listener from the session, if previously added.private void
scheduleEmptyRequest
(long delay) Schedule an empty request to be sent if no other requests are sent in a reasonable amount of time.void
send
(ComposableBody body) Send the provided message data to the remote connection manager.private void
Sends an empty request to maintain session requirements.(package private) void
setExchangeInterceptor
(BOSHClient.ExchangeInterceptor interceptor) Test method used to forcibly discard next exchange.
-
Field Details
-
LOG
Logger. -
TERMINATE
Value of the 'type' attribute used for session termination.- See Also:
-
ERROR
Value of the 'type' attribute used for recoverable errors.- See Also:
-
INTERRUPTED
Message to use for interrupted exceptions.- See Also:
-
UNHANDLED
Message used for unhandled exceptions.- See Also:
-
NULL_LISTENER
Message used whena null listener is detected.- See Also:
-
DEFAULT_EMPTY_REQUEST_DELAY
private static final int DEFAULT_EMPTY_REQUEST_DELAYDefault empty request delay.- See Also:
-
EMPTY_REQUEST_DELAY
private static final int EMPTY_REQUEST_DELAYAmount of time to wait before sending an empty request, in milliseconds. -
DEFAULT_PAUSE_MARGIN
private static final int DEFAULT_PAUSE_MARGINDefault value for the pause margin.- See Also:
-
PAUSE_MARGIN
private static final int PAUSE_MARGINThe 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 ASSERTIONSFlag indicating whether or not we want to perform assertions. -
connListeners
Connection listeners. -
requestListeners
Request listeners. -
responseListeners
Response listeners. -
lock
Lock instance. -
notEmpty
Condition indicating that there are messages to be exchanged. -
notFull
Condition indicating that there are available slots for sending messages. -
drained
Condition indicating that there are no outstanding connections. -
cfg
Session configuration. -
procRunnable
Processor thread runnable instance. -
emptyRequestRunnable
Processor thread runnable instance. -
httpSender
HTTPSender instance. -
exchInterceptor
Storage for test hook implementation. -
requestIDSeq
Request ID sequence to use for the session. -
schedExec
ScheduledExcecutor to use for deferred tasks. -
procThread
Thread which is used to process responses from the connection manager. Becomes null when session is terminated. -
emptyRequestFuture
Future for sending a deferred empty request, if needed. -
cmParams
Connection Manager session parameters. Only available when in a connected state. -
exchanges
List of active/outstanding requests. -
pendingResponseAcks
Set of RIDs which have been received, for the purpose of sending response acknowledgements. -
responseAck
The highest RID that we've already received a response for. This value is used to implement response acks. -
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
Prevent direct construction.
-
-
Method Details
-
create
Create a new BOSH client session using the client configuration information provided.- Parameters:
clientCfg
- session configuration- Returns:
- BOSH session instance
-
getBOSHClientConfig
Get the client configuration that was used to create this client instance.- Returns:
- client configuration
-
addBOSHClientConnListener
Adds a connection listener to the session.- Parameters:
listener
- connection listener to add, if not already added
-
removeBOSHClientConnListener
Removes a connection listener from the session.- Parameters:
listener
- connection listener to remove, if previously added
-
addBOSHClientRequestListener
Adds a request message listener to the session.- Parameters:
listener
- request listener to add, if not already added
-
removeBOSHClientRequestListener
Removes a request message listener from the session, if previously added.- Parameters:
listener
- instance to remove
-
addBOSHClientResponseListener
Adds a response message listener to the session.- Parameters:
listener
- response listener to add, if not already added
-
removeBOSHClientResponseListener
Removes a response message listener from the session, if previously added.- Parameters:
listener
- instance to remove
-
send
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
End the BOSH session by disconnecting from the remote BOSH connection manager.- Throws:
BOSHException
- when termination message cannot be sent
-
disconnect
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
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
Destroy this session.- Parameters:
cause
- the reason for the session termination, ornull
for normal termination
-
isPause
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
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
Evaluates the HTTP response code and response message and returns the terminal binding condition that it describes, if any.- Parameters:
respCode
- HTTP response coderespBody
- response body- Returns:
- terminal binding condition, or
null
if not a terminal binding condition message
-
isImmediatelySendable
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
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 useorig
- original body to modify- Returns:
- modified message which acts as a session creation request
- Throws:
BOSHException
-
applyRoute
Applies routing information to the request message who's builder has been provided.- Parameters:
builder
- builder instance to add routing information to
-
applyFrom
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
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 useorig
- original/raw request- Returns:
- modified request with session information applied
- Throws:
BOSHException
-
applyResponseAcknowledgement
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 builderrid
- current request RID
-
processMessages
private void processMessages()While we are "connected", process received responses. This method is run in the processing thread. -
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
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
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 evaluatecode
- HTTP response code- Throws:
BOSHException
- if a terminal binding condition is detected
-
isRecoverableBindingCondition
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
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
Check the response for request acknowledgements and take appropriate action. This method assumes the lock is currently held.- Parameters:
req
- requestresp
- response
-
processResponseAcknowledgementData
Process the response in order to update the response acknowlegement data. This method assumes the lock is currently held.- Parameters:
req
- request
-
processResponseAcknowledgementReport
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
Notifies all request listeners that the specified request is being sent.- Parameters:
request
- request being sent
-
fireResponseReceived
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
Notifies all connection listeners that the session has been terminated due to the exceptional condition provided.- Parameters:
cause
- cause of the termination
-