Search in sources :

Example 1 with WebSocketSessionAware

use of io.micronaut.websocket.interceptor.WebSocketSessionAware 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);
    }
}
Also used : CloseWebSocketFrame(io.netty.handler.codec.http.websocketx.CloseWebSocketFrame) Argument(io.micronaut.core.type.Argument) DefaultExecutableBinder(io.micronaut.core.bind.DefaultExecutableBinder) Channel(io.netty.channel.Channel) WebSocketClientException(io.micronaut.websocket.exceptions.WebSocketClientException) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) WebSocketSessionAware(io.micronaut.websocket.interceptor.WebSocketSessionAware) WebSocketClientException(io.micronaut.websocket.exceptions.WebSocketClientException) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) BoundExecutable(io.micronaut.core.bind.BoundExecutable) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) CloseWebSocketFrame(io.netty.handler.codec.http.websocketx.CloseWebSocketFrame) WebSocketFrame(io.netty.handler.codec.http.websocketx.WebSocketFrame) WebSocketPongMessage(io.micronaut.websocket.WebSocketPongMessage) WebSocketState(io.micronaut.websocket.bind.WebSocketState)

Aggregations

BoundExecutable (io.micronaut.core.bind.BoundExecutable)1 DefaultExecutableBinder (io.micronaut.core.bind.DefaultExecutableBinder)1 Argument (io.micronaut.core.type.Argument)1 WebSocketPongMessage (io.micronaut.websocket.WebSocketPongMessage)1 WebSocketState (io.micronaut.websocket.bind.WebSocketState)1 WebSocketClientException (io.micronaut.websocket.exceptions.WebSocketClientException)1 WebSocketSessionException (io.micronaut.websocket.exceptions.WebSocketSessionException)1 WebSocketSessionAware (io.micronaut.websocket.interceptor.WebSocketSessionAware)1 Channel (io.netty.channel.Channel)1 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)1 CloseWebSocketFrame (io.netty.handler.codec.http.websocketx.CloseWebSocketFrame)1 WebSocketFrame (io.netty.handler.codec.http.websocketx.WebSocketFrame)1