Class WsRemoteEndpointImplServer

    • Constructor Detail

      • WsRemoteEndpointImplServer

        public WsRemoteEndpointImplServer​(SocketWrapperBase<?> socketWrapper,
                                          UpgradeInfo upgradeInfo,
                                          WsServerContainer serverContainer,
                                          WebConnection connection)
        Constructs a server-side remote endpoint.
        Parameters:
        socketWrapper - the socket wrapper
        upgradeInfo - the upgrade information
        serverContainer - the server container
        connection - the web connection
    • Method Detail

      • acquireMessagePartInProgressSemaphore

        protected boolean acquireMessagePartInProgressSemaphore​(byte opCode,
                                                                long timeoutExpiry)
                                                         throws java.lang.InterruptedException
        Acquire the semaphore that allows a message part to be written.

        The close message is a special case. It needs to be blocking else implementing the clean-up that follows the sending of the close message gets a lot more complicated. On the server, this creates additional complications as a deadlock may occur in the following scenario:

        1. Application thread writes message using non-blocking
        2. Write does not complete (write logic holds message pending lock)
        3. Socket is added to poller (or equivalent) for write
        4. Client sends close message
        5. Container processes received close message and tries to send close message in response
        6. Container holds socket lock and is blocked waiting for message pending lock
        7. Poller fires write possible event for socket
        8. Container tries to process write possible event but is blocked waiting for socket lock
        9. Processing of the WebSocket connection is deadlocked until the original message write times out
        The purpose of this method is to break the above deadlock. It does this by returning control of the processor to the socket wrapper and releasing the socket lock while waiting for the pending message write to complete. Normally, that would be a terrible idea as it creates the possibility that the processor is returned to the pool more than once under various error conditions. In this instance it is safe because these are upgrade processors (isUpgrade() returns true) and upgrade processors are never pooled.

        TODO: Despite the complications it creates, it would be worth exploring the possibility of processing a received close frame in a non-blocking manner.

        Overrides:
        acquireMessagePartInProgressSemaphore in class WsRemoteEndpointImplBase
        Parameters:
        opCode - The OPCODE for the message to be written
        timeoutExpiry - The time when the attempt to acquire the semaphore should expire
        Returns:
        true if the semaphore is obtained, otherwise false.
        Throws:
        java.lang.InterruptedException - If the wait for the semaphore is interrupted
      • doWrite

        protected void doWrite​(SendHandler handler,
                               long blockingWriteTimeoutExpiry,
                               java.nio.ByteBuffer... buffers)
        Description copied from class: WsRemoteEndpointImplBase
        Writes data to the underlying connection.
        Specified by:
        doWrite in class WsRemoteEndpointImplBase
        Parameters:
        handler - the send handler
        blockingWriteTimeoutExpiry - the timeout expiry time
        buffers - the data buffers to write
      • updateStats

        protected void updateStats​(long payloadLength)
        Description copied from class: WsRemoteEndpointImplBase
        Hook for updating server side statistics. Called on every frame written (including when batching is enabled and the frames are buffered locally until the buffer is full or is flushed).
        Overrides:
        updateStats in class WsRemoteEndpointImplBase
        Parameters:
        payloadLength - Size of message payload
      • onWritePossible

        public void onWritePossible​(boolean useDispatch)
        Called when the underlying socket is ready for writing.
        Parameters:
        useDispatch - whether to use a dispatch for callback
      • getTimeoutExpiry

        protected long getTimeoutExpiry()
        Returns the timeout expiry time in milliseconds.
        Returns:
        the timeout expiry time
      • onTimeout

        protected void onTimeout​(boolean useDispatch)
        Handles a write timeout event.
        Parameters:
        useDispatch - whether to use a dispatch for callback