Search in sources :

Example 1 with SendResult

use of jakarta.websocket.SendResult in project atmosphere by Atmosphere.

the class JSR356WebSocketTest method test_semaphore_is_released_in_case_of_failing_write.

@Test(timeOut = 1000)
public void test_semaphore_is_released_in_case_of_failing_write() throws Exception {
    mockWriteResult(new SendResult(new RuntimeException("Fails")));
    webSocket.write("Hello");
    webSocket.write("Hello");
    verify(asyncRemoteEndpoint, times(2)).sendText(eq("Hello"), any(SendHandler.class));
}
Also used : SendHandler(jakarta.websocket.SendHandler) SendResult(jakarta.websocket.SendResult) Test(org.testng.annotations.Test)

Example 2 with SendResult

use of jakarta.websocket.SendResult in project tomcat by apache.

the class WsSession method doClose.

/**
 * WebSocket 1.0. Section 2.1.5.
 * Need internal close method as spec requires that the local endpoint
 * receives a 1006 on timeout.
 *
 * @param closeReasonMessage The close reason to pass to the remote endpoint
 * @param closeReasonLocal   The close reason to pass to the local endpoint
 * @param closeSocket        Should the socket be closed immediately rather than waiting
 *                           for the server to respond
 */
public void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal, boolean closeSocket) {
    // Double-checked locking. OK because state is volatile
    if (state != State.OPEN) {
        return;
    }
    synchronized (stateLock) {
        if (state != State.OPEN) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("wsSession.doClose", id));
        }
        // This will trigger a flush of any batched messages.
        try {
            wsRemoteEndpoint.setBatchingAllowed(false);
        } catch (IOException e) {
            log.warn(sm.getString("wsSession.flushFailOnClose"), e);
            fireEndpointOnError(e);
        }
        /*
             * If the flush above fails the error handling could call this
             * method recursively. Without this check, the close message and
             * notifications could be sent multiple times.
             */
        if (state != State.OUTPUT_CLOSED) {
            state = State.OUTPUT_CLOSED;
            sendCloseMessage(closeReasonMessage);
            if (closeSocket) {
                wsRemoteEndpoint.close();
            }
            fireEndpointOnClose(closeReasonLocal);
        }
    }
    IOException ioe = new IOException(sm.getString("wsSession.messageFailed"));
    SendResult sr = new SendResult(ioe);
    for (FutureToSendHandler f2sh : futures.keySet()) {
        f2sh.onResult(sr);
    }
}
Also used : SendResult(jakarta.websocket.SendResult) IOException(java.io.IOException)

Example 3 with SendResult

use of jakarta.websocket.SendResult in project tomcat by apache.

the class WsSession method registerFuture.

/**
 * Make the session aware of a {@link FutureToSendHandler} that will need to
 * be forcibly closed if the session closes before the
 * {@link FutureToSendHandler} completes.
 * @param f2sh The handler
 */
protected void registerFuture(FutureToSendHandler f2sh) {
    // Ideally, this code should sync on stateLock so that the correct
    // action is taken based on the current state of the connection.
    // However, a sync on stateLock can't be used here as it will create the
    // possibility of a dead-lock. See BZ 61183.
    // Therefore, a slightly less efficient approach is used.
    // Always register the future.
    futures.put(f2sh, f2sh);
    if (state == State.OPEN) {
        // session. Normal processing continues.
        return;
    }
    if (f2sh.isDone()) {
        // doesn't matter which. There is nothing more to do here.
        return;
    }
    // The session is closed. The Future had not completed when last checked.
    // There is a small timing window that means the Future may have been
    // completed since the last check. There is also the possibility that
    // the Future was not registered in time to be cleaned up during session
    // close.
    // Attempt to complete the Future with an error result as this ensures
    // that the Future completes and any client code waiting on it does not
    // hang. It is slightly inefficient since the Future may have been
    // completed in another thread or another thread may be about to
    // complete the Future but knowing if this is the case requires the sync
    // on stateLock (see above).
    // Note: If multiple attempts are made to complete the Future, the
    // second and subsequent attempts are ignored.
    IOException ioe = new IOException(sm.getString("wsSession.messageFailed"));
    SendResult sr = new SendResult(ioe);
    f2sh.onResult(sr);
}
Also used : SendResult(jakarta.websocket.SendResult) IOException(java.io.IOException)

Example 4 with SendResult

use of jakarta.websocket.SendResult in project tomcat by apache.

the class WsRemoteEndpointImplServer method clearHandler.

/**
 * @param t             The throwable associated with any error that
 *                      occurred
 * @param useDispatch   Should {@link SendHandler#onResult(SendResult)} be
 *                      called from a new thread, keeping in mind the
 *                      requirements of
 *                      {@link jakarta.websocket.RemoteEndpoint.Async}
 */
private void clearHandler(Throwable t, boolean useDispatch) {
    // Setting the result marks this (partial) message as
    // complete which means the next one may be sent which
    // could update the value of the handler. Therefore, keep a
    // local copy before signalling the end of the (partial)
    // message.
    SendHandler sh = handler;
    handler = null;
    buffers = null;
    if (sh != null) {
        if (useDispatch) {
            OnResultRunnable r = new OnResultRunnable(sh, t);
            try {
                socketWrapper.execute(r);
            } catch (RejectedExecutionException ree) {
                // Can't use the executor so call the runnable directly.
                // This may not be strictly specification compliant in all
                // cases but during shutdown only close messages are going
                // to be sent so there should not be the issue of nested
                // calls leading to stack overflow as described in bug
                // 55715. The issues with nested calls was the reason for
                // the separate thread requirement in the specification.
                r.run();
            }
        } else {
            if (t == null) {
                sh.onResult(new SendResult());
            } else {
                sh.onResult(new SendResult(t));
            }
        }
    }
}
Also used : SendHandler(jakarta.websocket.SendHandler) SendResult(jakarta.websocket.SendResult) RejectedExecutionException(java.util.concurrent.RejectedExecutionException)

Example 5 with SendResult

use of jakarta.websocket.SendResult in project tomcat by apache.

the class WsRemoteEndpointImplServer method doWrite.

@Override
protected void doWrite(SendHandler handler, long blockingWriteTimeoutExpiry, ByteBuffer... buffers) {
    if (socketWrapper.hasAsyncIO()) {
        final boolean block = (blockingWriteTimeoutExpiry != -1);
        long timeout = -1;
        if (block) {
            timeout = blockingWriteTimeoutExpiry - System.currentTimeMillis();
            if (timeout <= 0) {
                SendResult sr = new SendResult(new SocketTimeoutException());
                handler.onResult(sr);
                return;
            }
        } else {
            this.handler = handler;
            timeout = getSendTimeout();
            if (timeout > 0) {
                // Register with timeout thread
                timeoutExpiry = timeout + System.currentTimeMillis();
                wsWriteTimeout.register(this);
            }
        }
        socketWrapper.write(block ? BlockingMode.BLOCK : BlockingMode.SEMI_BLOCK, timeout, TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE_WITH_COMPLETION, new CompletionHandler<Long, Void>() {

            @Override
            public void completed(Long result, Void attachment) {
                if (block) {
                    long timeout = blockingWriteTimeoutExpiry - System.currentTimeMillis();
                    if (timeout <= 0) {
                        failed(new SocketTimeoutException(), null);
                    } else {
                        handler.onResult(SENDRESULT_OK);
                    }
                } else {
                    wsWriteTimeout.unregister(WsRemoteEndpointImplServer.this);
                    clearHandler(null, true);
                }
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                if (block) {
                    SendResult sr = new SendResult(exc);
                    handler.onResult(sr);
                } else {
                    wsWriteTimeout.unregister(WsRemoteEndpointImplServer.this);
                    clearHandler(exc, true);
                    close();
                }
            }
        }, buffers);
    } else {
        if (blockingWriteTimeoutExpiry == -1) {
            this.handler = handler;
            this.buffers = buffers;
            // This is definitely the same thread that triggered the write so a
            // dispatch will be required.
            onWritePossible(true);
        } else {
            // Blocking
            try {
                for (ByteBuffer buffer : buffers) {
                    long timeout = blockingWriteTimeoutExpiry - System.currentTimeMillis();
                    if (timeout <= 0) {
                        SendResult sr = new SendResult(new SocketTimeoutException());
                        handler.onResult(sr);
                        return;
                    }
                    socketWrapper.setWriteTimeout(timeout);
                    socketWrapper.write(true, buffer);
                }
                long timeout = blockingWriteTimeoutExpiry - System.currentTimeMillis();
                if (timeout <= 0) {
                    SendResult sr = new SendResult(new SocketTimeoutException());
                    handler.onResult(sr);
                    return;
                }
                socketWrapper.setWriteTimeout(timeout);
                socketWrapper.flush(true);
                handler.onResult(SENDRESULT_OK);
            } catch (IOException e) {
                SendResult sr = new SendResult(e);
                handler.onResult(sr);
            }
        }
    }
}
Also used : SocketTimeoutException(java.net.SocketTimeoutException) SendResult(jakarta.websocket.SendResult) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Aggregations

SendResult (jakarta.websocket.SendResult)9 IOException (java.io.IOException)6 SendHandler (jakarta.websocket.SendHandler)3 ByteBuffer (java.nio.ByteBuffer)3 SocketTimeoutException (java.net.SocketTimeoutException)2 Test (org.testng.annotations.Test)2 DeploymentException (jakarta.websocket.DeploymentException)1 EncodeException (jakarta.websocket.EncodeException)1 Encoder (jakarta.websocket.Encoder)1 OutputStream (java.io.OutputStream)1 Writer (java.io.Writer)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 CharsetEncoder (java.nio.charset.CharsetEncoder)1 ArrayList (java.util.ArrayList)1 ExecutionException (java.util.concurrent.ExecutionException)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 TimeoutException (java.util.concurrent.TimeoutException)1 NamingException (javax.naming.NamingException)1 Utf8Encoder (org.apache.tomcat.util.buf.Utf8Encoder)1