io.undertow.websockets.core.WebSockets Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.undertow.websockets.core;
import io.undertow.connector.PooledByteBuffer;
import io.undertow.util.ImmediatePooledByteBuffer;
import io.undertow.util.WorkerUtils;
import org.xnio.Buffers;
import org.xnio.ChannelExceptionHandler;
import org.xnio.ChannelListener;
import org.xnio.IoUtils;
import org.xnio.XnioExecutor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import static org.xnio.ChannelListeners.flushingChannelListener;
/**
* @author Stuart Douglas
*/
public class WebSockets {
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendText(final String message, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendText(message, wsChannel, callback, null);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendText(final String message, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
final ByteBuffer data = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8));
sendInternal(data, WebSocketFrameType.TEXT, wsChannel, callback, context, -1);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final String message, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendText(message, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final String message, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
final ByteBuffer data = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8));
sendInternal(data, WebSocketFrameType.TEXT, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendText(final ByteBuffer message, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(message, WebSocketFrameType.TEXT, wsChannel, callback, null, -1);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendText(final ByteBuffer message, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(message, WebSocketFrameType.TEXT, wsChannel, callback, context, -1);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final ByteBuffer message, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(message, WebSocketFrameType.TEXT, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final ByteBuffer message, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(message, WebSocketFrameType.TEXT, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendText(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(pooledData, WebSocketFrameType.TEXT, wsChannel, callback, null, -1);
}
/**
* Sends a complete text message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendText(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(pooledData, WebSocketFrameType.TEXT, wsChannel, callback, context, -1);
}
/**
* Sends a complete text message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.TEXT, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendText(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.TEXT, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
*/
public static void sendTextBlocking(final String message, final WebSocketChannel wsChannel) throws IOException {
final ByteBuffer data = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8));
sendBlockingInternal(data, WebSocketFrameType.TEXT, wsChannel);
}
/**
* Sends a complete text message, invoking the callback when complete
*
* @param message The text to send
* @param wsChannel The web socket channel
*/
public static void sendTextBlocking(final ByteBuffer message, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(message, WebSocketFrameType.TEXT, wsChannel);
}
/**
* Sends a complete text message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
*/
public static void sendTextBlocking(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(pooledData, WebSocketFrameType.TEXT, wsChannel);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPing(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(data, WebSocketFrameType.PING, wsChannel, callback, null, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPing(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(data, WebSocketFrameType.PING, wsChannel, callback, context, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.PING, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.PING, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPing(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PING, wsChannel, callback, null, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPing(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PING, wsChannel, callback, context, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PING, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete ping message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PING, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete ping message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPing(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(pooledData, WebSocketFrameType.PING, wsChannel, callback, null, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPing(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(pooledData, WebSocketFrameType.PING, wsChannel, callback, context, -1);
}
/**
* Sends a complete ping message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.PING, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete ping message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPing(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.PING, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete ping message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendPingBlocking(final ByteBuffer data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(data, WebSocketFrameType.PING, wsChannel);
}
/**
* Sends a complete ping message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendPingBlocking(final ByteBuffer[] data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(mergeBuffers(data), WebSocketFrameType.PING, wsChannel);
}
/**
* Sends a complete ping message using blocking IO
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
*/
public static void sendPingBlocking(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(pooledData, WebSocketFrameType.PING, wsChannel);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPong(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(data, WebSocketFrameType.PONG, wsChannel, callback, null, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPong(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(data, WebSocketFrameType.PONG, wsChannel, callback, context, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.PONG, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.PONG, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPong(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PONG, wsChannel, callback, null, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPong(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PONG, wsChannel, callback, context, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PONG, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete pong message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.PONG, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete pong message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendPong(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(pooledData, WebSocketFrameType.PONG, wsChannel, callback, null, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendPong(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(pooledData, WebSocketFrameType.PONG, wsChannel, callback, context, -1);
}
/**
* Sends a complete pong message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.PONG, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete pong message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendPong(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.PONG, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete pong message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendPongBlocking(final ByteBuffer data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(data, WebSocketFrameType.PONG, wsChannel);
}
/**
* Sends a complete pong message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendPongBlocking(final ByteBuffer[] data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(mergeBuffers(data), WebSocketFrameType.PONG, wsChannel);
}
/**
* Sends a complete pong message using blocking IO
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
*/
public static void sendPongBlocking(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(pooledData, WebSocketFrameType.PONG, wsChannel);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendBinary(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(data, WebSocketFrameType.BINARY, wsChannel, callback, null, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendBinary(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(data, WebSocketFrameType.BINARY, wsChannel, callback, context, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.BINARY, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(data, WebSocketFrameType.BINARY, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendBinary(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(mergeBuffers(data), WebSocketFrameType.BINARY, wsChannel, callback, null, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendBinary(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(mergeBuffers(data), WebSocketFrameType.BINARY, wsChannel, callback, context, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.BINARY, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete binary message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(mergeBuffers(data), WebSocketFrameType.BINARY, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete binary message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendBinary(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendInternal(pooledData, WebSocketFrameType.BINARY, wsChannel, callback, null, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendBinary(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendInternal(pooledData, WebSocketFrameType.BINARY, wsChannel, callback, context, -1);
}
/**
* Sends a complete binary message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.BINARY, wsChannel, callback, null, timeoutmillis);
}
/**
* Sends a complete binary message, invoking the callback when complete
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
* @param timeoutmillis the timeout in milliseconds
*/
public static void sendBinary(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(pooledData, WebSocketFrameType.BINARY, wsChannel, callback, context, timeoutmillis);
}
/**
* Sends a complete binary message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendBinaryBlocking(final ByteBuffer data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(data, WebSocketFrameType.BINARY, wsChannel);
}
/**
* Sends a complete binary message using blocking IO
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendBinaryBlocking(final ByteBuffer[] data, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(mergeBuffers(data), WebSocketFrameType.BINARY, wsChannel);
}
/**
* Sends a complete binary message using blocking IO
* Automatically frees the pooled byte buffer when done.
*
* @param pooledData The data to send, it will be freed when done
* @param wsChannel The web socket channel
*/
public static void sendBinaryBlocking(final PooledByteBuffer pooledData, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(pooledData, WebSocketFrameType.BINARY, wsChannel);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendClose(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
CloseMessage sm = new CloseMessage(data);
sendClose(sm, wsChannel, callback);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendClose(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
CloseMessage sm = new CloseMessage(data);
sendClose(sm, wsChannel, callback, context);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendClose(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
CloseMessage sm = new CloseMessage(data);
sendClose(sm, wsChannel, callback);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendClose(final ByteBuffer[] data, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
CloseMessage sm = new CloseMessage(data);
sendClose(sm, wsChannel, callback, context);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param code The close code
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendClose(final int code, String reason, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendClose(new CloseMessage(code, reason), wsChannel, callback);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param code The close code
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendClose(final int code, String reason, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
sendClose(new CloseMessage(code, reason), wsChannel, callback, context);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param closeMessage The close message
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
*/
public static void sendClose(final CloseMessage closeMessage, final WebSocketChannel wsChannel, final WebSocketCallback callback) {
sendClose(closeMessage, wsChannel, callback, null);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param closeMessage The close message
* @param wsChannel The web socket channel
* @param callback The callback to invoke on completion
* @param context The context object that will be passed to the callback on completion
*/
public static void sendClose(final CloseMessage closeMessage, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context) {
wsChannel.setCloseCode(closeMessage.getCode());
wsChannel.setCloseReason(closeMessage.getReason());
sendInternal(closeMessage.toByteBuffer(), WebSocketFrameType.CLOSE, wsChannel, callback, context, -1);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param closeMessage the close message
* @param wsChannel The web socket channel
*/
public static void sendCloseBlocking(final CloseMessage closeMessage, final WebSocketChannel wsChannel) throws IOException {
wsChannel.setCloseReason(closeMessage.getReason());
wsChannel.setCloseCode(closeMessage.getCode());
sendBlockingInternal(closeMessage.toByteBuffer(), WebSocketFrameType.CLOSE, wsChannel);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param code
* @param wsChannel The web socket channel
*/
public static void sendCloseBlocking(final int code, String reason, final WebSocketChannel wsChannel) throws IOException {
sendCloseBlocking(new CloseMessage(code, reason), wsChannel);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendCloseBlocking(final ByteBuffer data, final WebSocketChannel wsChannel) throws IOException {
sendCloseBlocking(new CloseMessage(data), wsChannel);
}
/**
* Sends a complete close message, invoking the callback when complete
*
* @param data The data to send
* @param wsChannel The web socket channel
*/
public static void sendCloseBlocking(final ByteBuffer[] data, final WebSocketChannel wsChannel) throws IOException {
sendCloseBlocking(new CloseMessage(data), wsChannel);
}
private static void sendInternal(final ByteBuffer data, WebSocketFrameType type, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
sendInternal(new ImmediatePooledByteBuffer(data), type, wsChannel, callback, context, timeoutmillis);
}
private static void sendInternal(final PooledByteBuffer pooledData, WebSocketFrameType type, final WebSocketChannel wsChannel, final WebSocketCallback callback, T context, long timeoutmillis) {
boolean closePooledData = true;
try {
StreamSinkFrameChannel channel = wsChannel.send(type);
// TODO chunk data into some MTU-like thing to control packet size
closePooledData = false; // channel.send takes ownership of pooledData so it no longer needs to be closed
if(!channel.send(pooledData)) {
throw WebSocketMessages.MESSAGES.unableToSendOnNewChannel();
}
flushChannelAsync(wsChannel, callback, channel, context, timeoutmillis);
} catch (IOException e) {
if (callback != null) {
callback.onError(wsChannel, context, e);
} else {
IoUtils.safeClose(wsChannel);
}
} finally {
if ( closePooledData ) {
pooledData.close();
}
}
}
private static void flushChannelAsync(final WebSocketChannel wsChannel, final WebSocketCallback callback, StreamSinkFrameChannel channel, final T context, long timeoutmillis) throws IOException {
final WebSocketFrameType type = channel.getType();
channel.shutdownWrites();
if (!channel.flush()) {
channel.getWriteSetter().set(flushingChannelListener(
new ChannelListener() {
@Override
public void handleEvent(StreamSinkFrameChannel channel) {
if (callback != null) {
callback.complete(wsChannel, context);
}
if (type == WebSocketFrameType.CLOSE && wsChannel.isCloseFrameReceived()) {
IoUtils.safeClose(wsChannel);
}
//we explicitly set the channel to null, as in some situations this
//listener may get invoked twice
channel.getWriteSetter().set(null);
}
}, new ChannelExceptionHandler() {
@Override
public void handleException(StreamSinkFrameChannel channel, IOException exception) {
if (callback != null) {
callback.onError(wsChannel, context, exception);
}
IoUtils.safeClose(channel, wsChannel);
//we explicitly set the channel to null, as in some situations this
//listener may get invoked twice
channel.getWriteSetter().set(null);
}
}
));
if(timeoutmillis > 0) {
setupTimeout(channel, timeoutmillis);
}
channel.resumeWrites();
return;
}
if (callback != null) {
callback.complete(wsChannel, context);
}
}
private static void setupTimeout(final StreamSinkFrameChannel channel, long timeoutmillis) {
final XnioExecutor.Key key = WorkerUtils.executeAfter(channel.getIoThread(), new Runnable() {
@Override
public void run() {
if (channel.isOpen()) {
IoUtils.safeClose(channel);
}
}
}, timeoutmillis, TimeUnit.MILLISECONDS);
channel.getCloseSetter().set(new ChannelListener() {
@Override
public void handleEvent(StreamSinkFrameChannel channel) {
key.remove();
}
});
}
private static void sendBlockingInternal(final ByteBuffer data, WebSocketFrameType type, final WebSocketChannel wsChannel) throws IOException {
sendBlockingInternal(new ImmediatePooledByteBuffer(data), type, wsChannel);
}
private static void sendBlockingInternal(final PooledByteBuffer pooledData, WebSocketFrameType type, final WebSocketChannel wsChannel) throws IOException {
boolean closePooledData = true;
try {
StreamSinkFrameChannel channel = wsChannel.send(type);
// TODO chunk data into some MTU-like thing to control packet size
closePooledData = false; // channel.send takes ownership of pooledData so it no longer needs to be closed
if(!channel.send(pooledData)) {
throw WebSocketMessages.MESSAGES.unableToSendOnNewChannel();
}
channel.shutdownWrites();
while (!channel.flush()) {
channel.awaitWritable();
}
if (type == WebSocketFrameType.CLOSE && wsChannel.isCloseFrameReceived()) {
IoUtils.safeClose(wsChannel);
}
} finally {
if (closePooledData) {
pooledData.close();
}
}
}
private WebSockets() {
}
public static ByteBuffer mergeBuffers(ByteBuffer... payload) {
int size = (int) Buffers.remaining(payload);
if (size == 0) {
return Buffers.EMPTY_BYTE_BUFFER;
}
ByteBuffer buffer = ByteBuffer.allocate(size);
for (ByteBuffer buf : payload) {
buffer.put(buf);
}
buffer.flip();
return buffer;
}
}