Class Exchange

java.lang.Object
org.eclipse.californium.core.network.Exchange

public class Exchange extends Object
An exchange represents the complete state of an exchange of one request and one or more responses. The lifecycle of an exchange ends when either the last response has arrived and is acknowledged, when a request or response has been rejected from the remote endpoint, when the request has been canceled, or when a request or response timed out, i.e., has reached the retransmission limit without being acknowledged.

The framework internally uses the class Exchange to manage an exchange of Requests and Responses. The Exchange only contains state, no functionality. The CoAP Stack contains the functionality of the CoAP protocol and modifies the exchange appropriately. The class Exchange and its fields are NOT thread-safe. The setter methods must be called within a Runnable, which must be executed using execute(Runnable). For convenience the executeComplete() is provided to execute setComplete() accordingly. Methods, which are documented to throw a ConcurrentModificationException MUST comply to this execution pattern!

If the exchange represents a "blockwise" transfer and if the transparent mode is used, the exchange keeps also the (original) request and use the current request for transfer the blocks. A request not using observe use the same token for easier tracking. A request using observe keeps the origin request with the origin token in store, but use a different token for the transfer of the left blocks. This enables to catch new notifies while a transfer is ongoing.

The class CoapExchange provides the corresponding API for developers. Proceed with caution when using this class directly, e.g., through CoapExchange.advanced().

This class might change with the implementation of CoAP extensions.

Even if above mentions, that this class is not thread safe, its used from several different threads! Generally the Exchanges are hand over via a concurrent collections in the matcher and therefore establish a "happens before" order (as long as threads accessing the exchange via the matcher). But some methods are out of scope of that and use Exchange directly (e.g. setEndpointContext(EndpointContext) the "sender thread"). Therefore some fields use at least volatile. This doesn't ensure, that Exchange is thread safe, it only ensures the visibility of the states.

  • Constructor Details

    • Exchange

      public Exchange(Request request, Object peersIdentity, Exchange.Origin origin, Executor executor)
      Creates a new exchange with the specified request and origin. Note: since 3.9 null as executor doesn't longer fail with a NullPointerException. Using null is still not supported and comes with risks, that especially requires your own responsibility.
      Parameters:
      request - the request that starts the exchange
      peersIdentity - peer's identity. Usually that's the peer's InetSocketAddress.
      origin - the origin of the request (LOCAL or REMOTE)
      executor - executor to be used for exchanges.
      Throws:
      NullPointerException - if request is null
      Since:
      3.0 (added peersIdentity, executor adapted to mandatory)
      See Also:
      • EndpointIdentityResolver
    • Exchange

      public Exchange(Request request, Object peersIdentity, Exchange.Origin origin, Executor executor, org.eclipse.californium.elements.EndpointContext ctx, boolean notification)
      Creates a new exchange with the specified request, origin, context, and notification marker. Note: since 3.9 null as executor doesn't longer fail with a NullPointerException. Using null is still not supported and comes with risks, that especially requires your own responsibility.
      Parameters:
      request - the request that starts the exchange
      peersIdentity - peer's identity. Usually that's the peer's InetSocketAddress.
      origin - the origin of the request (LOCAL or REMOTE)
      executor - executor to be used for exchanges.
      ctx - the endpoint context of this exchange
      notification - true for notification exchange, false otherwise
      Throws:
      NullPointerException - if request is null
      Since:
      3.0 (added peersIdentity, executor adapted to mandatory)
      See Also:
      • EndpointIdentityResolver
  • Method Details

    • toString

      public String toString()
      Overrides:
      toString in class Object
    • sendAccept

      public void sendAccept()
      Accept this exchange and therefore the request. Only if the request's type was a CON and the request has not been acknowledged yet, it sends an ACK to the client. Use the source endpoint context of the current request to send the ACK.
      See Also:
    • sendAccept

      public void sendAccept(org.eclipse.californium.elements.EndpointContext context)
      Accept this exchange and therefore the request. Only if the request's type was a CON and the request has not been acknowledged yet, it sends an ACK to the client and prepares to send the response as separate response.
      Parameters:
      context - endpoint context to send ack
      See Also:
    • sendReject

      public void sendReject()
      Reject this exchange and therefore the request. Sends an RST back to the client, if the request has not been already rejected. Use the source endpoint context of the current request to send the RST. Note: since 2.3, rejects for multicast requests are not sent. (See UdpMulticastConnector for receiving multicast requests).
      Since:
      2.3 rejects for multicast requests are not sent
      See Also:
    • sendReject

      public void sendReject(org.eclipse.californium.elements.EndpointContext context)
      Reject this exchange and therefore the request. Sends an RST back to the client, if the request has not been already rejected. Note: since 2.3, rejects for multicast requests are not sent. (See UdpMulticastConnector for receiving multicast requests).
      Parameters:
      context - endpoint context to send RST
      Since:
      2.3 rejects for multicast requests are not sent
      See Also:
    • sendResponse

      public void sendResponse(Response response)
      Sends the specified response over the same endpoint as the request has arrived. If no destination context is provided, use the source context of the request. Note: since 2.3, error responses for multicast requests are not sent. (See UdpMulticastConnector for receiving multicast requests). Note: since 3.0, NoResponseOption is considered. That may cause to send error responses also for multicast requests.
      Parameters:
      response - the response
      Since:
      2.3 error responses for multicast requests are not sent, 3.0 NoResponseOption is considered
    • getOrigin

      public Exchange.Origin getOrigin()
    • isOfLocalOrigin

      public boolean isOfLocalOrigin()
    • getRemoteSocketAddress

      public InetSocketAddress getRemoteSocketAddress()
      Get remote socket address. Get remote socket address of current request.
      Returns:
      current remote socket address
      Throws:
      IllegalArgumentException - if corresponding endpoint context is missing
      Since:
      3.8
    • keepsRequestInStore

      public boolean keepsRequestInStore()
      Indicate to keep the original request in the exchange store. Intended to be used for observe request with blockwise response to be able to react on newer notifies during an ongoing transfer.
      Returns:
      true to keep it, false, otherwise
    • isNotification

      public boolean isNotification()
      Indicate a notification exchange.
      Returns:
      true if notification is exchanged, false, otherwise
    • getRequest

      public Request getRequest()
      Returns the request that this exchange is associated with. If the request is sent blockwise, it might not have been assembled yet and this method returns null.
      Returns:
      the complete request
      See Also:
    • setRequest

      public void setRequest(Request newRequest)
      Sets the request that this exchange is associated with.
      Parameters:
      newRequest - the request
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
      See Also:
    • getCurrentRequest

      public Request getCurrentRequest()
      Returns the current request block. If a request is not being sent blockwise, the whole request counts as a single block and this method returns the same request as getRequest(). Call getRequest() to access the assembled request.
      Returns:
      the current request block
    • setCurrentRequest

      public void setCurrentRequest(Request newCurrentRequest)
      Sets the current request block. If a request is not being sent blockwise, the origin request (equal to getRequest()) should be set.
      Parameters:
      newCurrentRequest - the current request block
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • getResponse

      public Response getResponse()
      Returns the response to the request or null, if no response has arrived yet. If there is an observe relation, the last received notification is the response on the client side. On the server side, that is the last notification to be sent, but may differ from the current response, if that is in transit.
      Returns:
      the response. or null,
    • setResponse

      public void setResponse(Response response)
      Sets the response.
      Parameters:
      response - the response
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • getCurrentResponse

      public Response getCurrentResponse()
      Returns the current response block. If a response is not being sent blockwise, the whole response counts as a single block and this method returns the same response as getResponse(). Call getResponse() to access the assembled response. On the server-side, this is the current notification in flight.
      Returns:
      the current response block, or current notification in flight.
    • setCurrentResponse

      public void setCurrentResponse(Response newCurrentResponse)
      Sets the current response block. If a response is not being sent blockwise, the origin response (equal to getResponse()) should be set.
      Parameters:
      newCurrentResponse - the current response block
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • getKeyMID

      public KeyMID getKeyMID()
    • setKeyMID

      public void setKeyMID(KeyMID keyMID)
      Set key mid used to register this exchange.
      Parameters:
      keyMID - key mid.
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • setKeyToken

      public void setKeyToken(KeyToken keyToken)
      Set key token used to register this exchange.
      Parameters:
      keyToken - key token
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • getKeyToken

      public KeyToken getKeyToken()
    • getBlock1ToAck

      public BlockOption getBlock1ToAck()
      Returns the block option of the last block of a blockwise sent request. When the server sends the response, this block option has to be acknowledged.
      Returns:
      the block option of the last request block or null
    • setBlock1ToAck

      public void setBlock1ToAck(BlockOption block1ToAck)
      Sets the block option of the last block of a blockwise sent request. When the server sends the response, this block option has to be acknowledged.
      Parameters:
      block1ToAck - the block option of the last request block
    • getEndpoint

      public Endpoint getEndpoint()
      Returns the endpoint which has created and processed this exchange.
      Returns:
      the endpoint
    • setEndpoint

      public void setEndpoint(Endpoint endpoint)
      Set endpoint of received message.
      Parameters:
      endpoint - endpoint, which received the message.
    • getPeersIdentity

      public Object getPeersIdentity()
      Returns the other peer's identity.
      Returns:
      the other peer's identity
      Since:
      3.0
      See Also:
      • EndpointIdentityResolver
    • isTimedOut

      public boolean isTimedOut()
      Indicated, that this exchange retransmission reached the timeout.
      Returns:
      true, transmission reached timeout, false, otherwise
    • setTimedOut

      public void setTimedOut(Message message)
      Report transmission timeout for provided message to exchange.

      This method also cleans up the Matcher state by calling the exchange observer setComplete(). The timeout is forward to the provided message, and, for the currentRequest, it is also forwarded to the request to timeout the blockwise transfer itself. If the exchange was already completed, this method doesn't forward the timeout calls to the requests.

      Parameters:
      message - message, which transmission has reached the timeout.
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • getFailedTransmissionCount

      public int getFailedTransmissionCount()
      Get failed transmissions count.
      Returns:
      number of failed transmissions
    • incrementFailedTransmissionCount

      public int incrementFailedTransmissionCount()
      Increment the failed transmission count.
      Returns:
      incremented number of failed transmissions
      Since:
      3.0
    • getTimeoutScale

      public float getTimeoutScale()
      Get timeout scale factor for exponential back-off between retransmissions.
      Returns:
      timeout scale factor for exponential back-off.
      Since:
      3.0
    • setTimeoutScale

      public void setTimeoutScale(float scale)
      Set timeout scale factor for exponential back-off between retransmissions.
      Parameters:
      scale - timeout scale factor. Must be at least 1.0. If larger than 1.0, an exponential back-off between retransmissions is used.
      Throws:
      IllegalArgumentException - if value is not at least 1.0.
      Since:
      3.0
    • getCurrentTimeout

      public int getCurrentTimeout()
      Get current timeout. Timeout for retransmission, if no ACK, RST nor response is received.
      Returns:
      current timeout in milliseconds
    • setCurrentTimeout

      public void setCurrentTimeout(int currentTimeout)
      Set current timeout. Timeout for retransmission, if no ACK, RST nor response is received.
      Parameters:
      currentTimeout - current timeout in milliseconds. Must be larger than 0.
    • isTransmissionPending

      public boolean isTransmissionPending()
      Check, if ACK, RST or response for transmission is pending.
      Returns:
      true, if ACK, RST or response is pending, false, if not.
      Since:
      3.0 (was getRetransmissionHandle)
    • setRetransmissionHandle

      public void setRetransmissionHandle(ScheduledFuture<?> newRetransmissionHandle)
      Set retransmission handle.
      Parameters:
      newRetransmissionHandle - new retransmission handle. May be null, if no retransmission is required.
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • retransmitResponse

      public void retransmitResponse()
      Prepare exchange for retransmit a response.
      Throws:
      IllegalStateException - if exchange is not a REMOTE exchange.
      ConcurrentModificationException - if not executed within execute(Runnable).
    • setNotificationNumber

      public void setNotificationNumber(int notificationNo)
      Sets the number of the notification this exchange is associated with.

      This number can be used to match responses of a blockwise transfer triggered by a notification.

      Parameters:
      notificationNo - The observe number of the notification.
      Throws:
      IllegalArgumentException - if the given number is < 0 or > 2^24 - 1.
    • getNotificationNumber

      public Integer getNotificationNumber()
      Gets the number of the notification this exchange is associated with.

      This number can be used to match responses of a blockwise transfer triggered by a notification.

      Returns:
      The observe number of the notification or null if this exchange is not associated with a notification.
    • setRemoveHandler

      public void setRemoveHandler(RemoveHandler removeHandler)
      Sets an remove handler to be invoked when this exchange completes.
      Parameters:
      removeHandler - The remove handler.
    • hasRemoveHandler

      public boolean hasRemoveHandler()
      Checks whether this exchange has an remove handler set.
      Returns:
      true if an remove handler is set.
      See Also:
    • isComplete

      public boolean isComplete()
      Checks if this exchange has been marked as completed.
      Returns:
      true, if this exchange has been completed.
    • getCaller

      public Throwable getCaller()
      Get caller.
      Returns:
      the caller's stacktrace.
    • setComplete

      public boolean setComplete()
      Marks this exchange as being completed.

      This means that both request and response have been sent/received.

      This method invokes the remove method on the observer registered on this exchange (if any).

      Call this method to trigger a clean-up in the Matcher through its ExchangeObserverImpl. Usually, it is called automatically when reaching the StackTopAdapter in the CoapStack, when timing out, when rejecting a response, or when sending the (last) response.

      Returns:
      true, if complete is set the first time, false, if it is repeated.
      Throws:
      ExchangeCompleteException - if exchange was already completed.
      ConcurrentModificationException - if not executed within execute(Runnable).
    • executeComplete

      public boolean executeComplete()
      Execute complete. Schedules job for this exchange, if current thread is not already owner of it.
      Returns:
      true, if exchange was not already completed, false, if exchange is already completed.
    • getNanoTimestamp

      public long getNanoTimestamp()
      Get the nano-timestamp of the creation of this exchange.
      Returns:
      nano-timestamp
      See Also:
      • ClockUtil.nanoRealtime()
    • getSendNanoTimestamp

      public long getSendNanoTimestamp()
      Get the realtime of the last sending of a message in nanoseconds. The realtime is just before sending this message to ensure, that the message wasn't sent up to this time. This will also contain the realtime for ACK or RST messages.
      Returns:
      nano-time of last message sending. 0, if no message was sent until now. In the extremely rare cases, that the realtime in nanosecond is actually 0, the value is adapted to -1.
      See Also:
      • ClockUtil.nanoRealtime()
    • setSendNanoTimestamp

      public void setSendNanoTimestamp(long nanoTimestamp)
      Set the realtime of the last sending of a message in nanoseconds.
      Parameters:
      nanoTimestamp - realtime in nanoseconds.0, if no message was sent until now. In the extremely rare cases, that the realtime in nanosecond is actually 0, the value must be adapted to -1.
    • startTransmissionRtt

      public void startTransmissionRtt()
      Start transmission RTT.
      Since:
      3.0
    • calculateTransmissionRtt

      public long calculateTransmissionRtt()
      Calculate transmission round trip time. startTransmissionRtt() must be called before.
      Returns:
      transmission round trip time in nanoseconds.
      Throws:
      IllegalStateException - if startTransmissionRtt() wasn't called before.
      Since:
      3.0
    • calculateApplicationRtt

      public long calculateApplicationRtt()
      Calculates the RTT (round trip time) of this exchange. MUST be called on receiving the response.
      Returns:
      RTT in nanoseconds
      Since:
      3.0 (was calculateRTT returning milliseconds)
    • getRelation

      public ObserveRelation getRelation()
      Returns the CoAP observe relation that this exchange has initially established.

      Note: in the meantime the relation may have been ObserveRelation.cancel(). Therefore it's important to check the current state of the relation using ObserveRelation.isCanceled() or ObserveRelation.isEstablished().

      Returns:
      the observe relation, or null, if this exchange is not related to an observation.
    • setRelation

      public void setRelation(ObserveRelation relation)
      Sets the observe relation this exchange has established.
      Parameters:
      relation - the CoAP observe relation
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
      NullPointerException - if provided relation is null
      IllegalStateException - if relation was already set before
    • removeNotifications

      public void removeNotifications()
      Remove past notifications from message exchange store. To be able to react on RST for notifications, the NON notifications are also kept in the message exchange store. This method removes the notification message from the store.
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
    • setEndpointContext

      public void setEndpointContext(org.eclipse.californium.elements.EndpointContext ctx)
      Sets additional information about the context this exchange's request has been sent in.

      The information is usually obtained from the Connector this exchange is using to send and receive data. The information contained in the context can be used in addition to the message ID and token of this exchange to increase security when matching an incoming response to this exchange's request.

      If a setEndpointContextPreOperator(EndpointContextOperator) is used, this pre-operator is called before the endpoint context is set and forwarded.
      Parameters:
      ctx - the endpoint context information
    • resetEndpointContext

      public void resetEndpointContext()
    • getEndpointContext

      public org.eclipse.californium.elements.EndpointContext getEndpointContext()
      Gets transport layer specific information that can be used to correlate a response with this exchange's original request.
      Returns:
      the endpoint context information or null, if no information is available.
    • setEndpointContextPreOperator

      public void setEndpointContextPreOperator(Exchange.EndpointContextOperator operator)
      Set endpoint context pre-operator. Applied on setEndpointContext(EndpointContext) before the endpoint context is set and forwarded.
      Parameters:
      operator - preprocessing operator for endoint context.
    • execute

      public void execute(Runnable command)
      Execute a job serialized related to this exchange. If exchange is already owned by the current thread, execute it synchronous. Otherwise schedule the execution.
      Parameters:
      command - job
    • assertIncomplete

      public void assertIncomplete(Object message)
      Assert, that the exchange is not complete and new messages could be send using this exchange.
      Parameters:
      message - message to be send using this exchange.
      Throws:
      ConcurrentModificationException - if not executed within execute(Runnable).
      ExchangeCompleteException - if exchange is already completed
    • checkOwner

      public boolean checkOwner()
      Check, if current thread owns this exchange.
      Returns:
      true, if current thread owns this exchange, false, otherwise.
    • setCryptographicContextID

      public void setCryptographicContextID(byte[] cryptoContextId)
      Sets cryptoContextId
      Parameters:
      cryptoContextId - a byte array used for mapping cryptographic contexts
    • getCryptographicContextID

      public byte[] getCryptographicContextID()
      Gets cryptoContextId. Used by OSCORE.
      Returns:
      byte array with crypto context id.