use of io.micronaut.websocket.exceptions.WebSocketSessionException in project micronaut-core by micronaut-projects.
the class NettyWebSocketClientHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
final Channel ch = ctx.channel();
if (!handshaker.isHandshakeComplete()) {
// web socket client connected
FullHttpResponse res = (FullHttpResponse) msg;
this.handshakeResponse = res;
try {
handshaker.finishHandshake(ch, res);
} catch (Exception e) {
try {
emitter.error(new WebSocketClientException("Error finishing WebSocket handshake: " + e.getMessage(), e));
} finally {
// clientSession isn't set yet, so we do the close manually instead of through session.close
ch.writeAndFlush(new CloseWebSocketFrame(CloseReason.INTERNAL_ERROR.getCode(), CloseReason.INTERNAL_ERROR.getReason()));
ch.close();
}
return;
}
handshakeFuture.setSuccess();
this.clientSession = createWebSocketSession(ctx);
T targetBean = genericWebSocketBean.getTarget();
if (targetBean instanceof WebSocketSessionAware) {
((WebSocketSessionAware) targetBean).setWebSocketSession(clientSession);
}
ExecutableBinder<WebSocketState> binder = new DefaultExecutableBinder<>();
BoundExecutable<?, ?> bound = binder.tryBind(messageHandler.getExecutableMethod(), webSocketBinder, new WebSocketState(clientSession, originatingRequest));
List<Argument<?>> unboundArguments = bound.getUnboundArguments();
if (unboundArguments.size() == 1) {
this.clientBodyArgument = unboundArguments.iterator().next();
} else {
this.clientBodyArgument = null;
try {
emitter.error(new WebSocketClientException("WebSocket @OnMessage method " + targetBean.getClass().getSimpleName() + "." + messageHandler.getExecutableMethod() + " should define exactly 1 message parameter, but found 2 possible candidates: " + unboundArguments));
} finally {
if (getSession().isOpen()) {
getSession().close(CloseReason.INTERNAL_ERROR);
}
}
return;
}
if (pongHandler != null) {
BoundExecutable<?, ?> boundPong = binder.tryBind(pongHandler.getExecutableMethod(), webSocketBinder, new WebSocketState(clientSession, originatingRequest));
List<Argument<?>> unboundPongArguments = boundPong.getUnboundArguments();
if (unboundPongArguments.size() == 1 && unboundPongArguments.get(0).isAssignableFrom(WebSocketPongMessage.class)) {
this.clientPongArgument = unboundPongArguments.get(0);
} else {
this.clientPongArgument = null;
try {
emitter.error(new WebSocketClientException("WebSocket @OnMessage pong handler method " + targetBean.getClass().getSimpleName() + "." + messageHandler.getExecutableMethod() + " should define exactly 1 pong message parameter, but found: " + unboundArguments));
} finally {
if (getSession().isOpen()) {
getSession().close(CloseReason.INTERNAL_ERROR);
}
}
return;
}
}
Optional<? extends MethodExecutionHandle<?, ?>> opt = webSocketBean.openMethod();
if (opt.isPresent()) {
MethodExecutionHandle<?, ?> openMethod = opt.get();
WebSocketState webSocketState = new WebSocketState(clientSession, originatingRequest);
try {
BoundExecutable openMethodBound = binder.bind(openMethod.getExecutableMethod(), webSocketStateBinderRegistry, webSocketState);
Object target = openMethod.getTarget();
Object result = openMethodBound.invoke(target);
if (Publishers.isConvertibleToPublisher(result)) {
Publisher<?> reactiveSequence = Publishers.convertPublisher(result, Publisher.class);
Flux.from(reactiveSequence).subscribe(o -> {
}, error -> emitter.error(new WebSocketSessionException("Error opening WebSocket client session: " + error.getMessage(), error)), () -> {
emitter.next(targetBean);
emitter.complete();
});
} else {
emitter.next(targetBean);
emitter.complete();
}
} catch (Throwable e) {
emitter.error(new WebSocketClientException("Error opening WebSocket client session: " + e.getMessage(), e));
if (getSession().isOpen()) {
getSession().close(CloseReason.INTERNAL_ERROR);
}
}
} else {
emitter.next(targetBean);
emitter.complete();
}
return;
}
if (msg instanceof WebSocketFrame) {
handleWebSocketFrame(ctx, (WebSocketFrame) msg);
} else {
ctx.fireChannelRead(msg);
}
}
use of io.micronaut.websocket.exceptions.WebSocketSessionException in project micronaut-core by micronaut-projects.
the class NettyWebSocketSession method sendAsync.
@Override
public <T> CompletableFuture<T> sendAsync(T message, MediaType mediaType) {
if (isOpen()) {
if (message != null) {
CompletableFuture<T> future = new CompletableFuture<>();
WebSocketFrame frame;
if (message instanceof WebSocketFrame) {
frame = (WebSocketFrame) message;
} else {
frame = messageEncoder.encodeMessage(message, mediaType);
}
channel.writeAndFlush(frame).addListener(f -> {
if (f.isSuccess()) {
future.complete(message);
} else {
future.completeExceptionally(new WebSocketSessionException("Send Failure: " + f.cause().getMessage(), f.cause()));
}
});
return future;
} else {
return CompletableFuture.completedFuture(null);
}
} else {
throw new WebSocketSessionException("Session closed");
}
}
use of io.micronaut.websocket.exceptions.WebSocketSessionException in project micronaut-core by micronaut-projects.
the class NettyServerWebSocketBroadcaster method broadcast.
@Override
public <T> Publisher<T> broadcast(T message, MediaType mediaType, Predicate<WebSocketSession> filter) {
return Flux.create(emitter -> {
try {
WebSocketFrame frame = webSocketMessageEncoder.encodeMessage(message, mediaType);
webSocketSessionRepository.getChannelGroup().writeAndFlush(frame, ch -> {
Attribute<NettyWebSocketSession> attr = ch.attr(NettyWebSocketSession.WEB_SOCKET_SESSION_KEY);
NettyWebSocketSession s = attr.get();
return s != null && s.isOpen() && filter.test(s);
}).addListener(future -> {
if (!future.isSuccess()) {
Throwable cause = extractBroadcastFailure(future.cause());
if (cause != null) {
emitter.error(new WebSocketSessionException("Broadcast Failure: " + cause.getMessage(), cause));
return;
}
}
emitter.next(message);
emitter.complete();
});
} catch (Throwable e) {
emitter.error(new WebSocketSessionException("Broadcast Failure: " + e.getMessage(), e));
}
}, FluxSink.OverflowStrategy.BUFFER);
}
use of io.micronaut.websocket.exceptions.WebSocketSessionException in project micronaut-core by micronaut-projects.
the class NettyWebSocketSession method send.
@Override
public <T> Flux<T> send(T message, MediaType mediaType) {
if (message == null) {
return Flux.empty();
}
return Flux.create(emitter -> {
if (!isOpen()) {
emitter.error(new WebSocketSessionException("Session closed"));
} else {
WebSocketFrame frame;
if (message instanceof WebSocketFrame) {
frame = (WebSocketFrame) message;
} else {
frame = messageEncoder.encodeMessage(message, mediaType);
}
ChannelFuture channelFuture = channel.writeAndFlush(frame);
channelFuture.addListener(future -> {
if (future.isSuccess()) {
emitter.next(message);
emitter.complete();
} else {
emitter.error(new WebSocketSessionException("Send Failure: " + future.cause().getMessage(), future.cause()));
}
});
}
}, FluxSink.OverflowStrategy.ERROR);
}
use of io.micronaut.websocket.exceptions.WebSocketSessionException in project micronaut-core by micronaut-projects.
the class NettyWebSocketSession method sendPingAsync.
@NonNull
@Override
public CompletableFuture<?> sendPingAsync(@NonNull byte[] content) {
if (isOpen()) {
ByteBuf messageBuffer = channel.alloc().buffer(content.length);
messageBuffer.writeBytes(content);
PingWebSocketFrame frame = new PingWebSocketFrame(messageBuffer);
CompletableFuture<Object> future = new CompletableFuture<>();
channel.writeAndFlush(frame).addListener(f -> {
if (f.isSuccess()) {
future.complete(null);
} else {
future.completeExceptionally(new WebSocketSessionException("Send Failure: " + f.cause().getMessage(), f.cause()));
}
});
return future;
} else {
throw new WebSocketSessionException("Session closed");
}
}
Aggregations