All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sirius.web.http.WebsocketHandler Maven / Gradle / Ivy

/*
 * Made with all the love in the world
 * by scireum in Remshalden, Germany
 *
 * Copyright by scireum GmbH
 * http://www.scireum.de - [email protected]
 */

package sirius.web.http;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import sirius.kernel.health.Exceptions;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;

/**
 * Inserted into the pipeline by the {@link WebServerInitializer} if an implementation of {@link WebsocketDispatcher}
 * is
 * present.
 */
public class WebsocketHandler extends ChannelDuplexHandler {

    private WebsocketSession websocketSession;
    private WebsocketDispatcher websocketDispatcher;

    /**
     * Creates a new handler (one per connection) talking to the given dispatcher.
     *
     * @param websocketDispatcher the dispatcher responsible for creating a {@link WebsocketSession}
     */
    public WebsocketHandler(WebsocketDispatcher websocketDispatcher) {
        this.websocketDispatcher = websocketDispatcher;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
        if (e instanceof ClosedChannelException || e instanceof IOException) {
            WebServer.LOG.FINE(e);
        } else {
            Exceptions.handle(WebServer.LOG, e);
        }
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        if (websocketSession != null) {
            websocketSession.onWebsocketClosed();
            WebServer.websockets--;
        }

        super.channelUnregistered(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
            if (websocketSession != null) {
                websocketSession.onWebsocketOpened();
            }
        }

        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest && isWebsocketRequest(ctx, (HttpRequest) msg)) {
            websocketSession = websocketDispatcher.createSession(ctx, (HttpRequest) msg);
            WebServer.websockets++;
            setupWebsocketPipeline(ctx, msg);
            return;
        }

        if (msg instanceof WebSocketFrame) {
            if (websocketSession != null) {
                websocketSession.onFrame((WebSocketFrame) msg);
            } else {
                try {
                    ctx.channel().close();
                } catch (Exception e) {
                    Exceptions.handle(WebServer.LOG, e);
                }
            }
            ((WebSocketFrame) msg).release();

            return;
        }

        super.channelRead(ctx, msg);
    }

    private void setupWebsocketPipeline(ChannelHandlerContext ctx, Object msg) throws Exception {
        HttpObjectAggregator handler = new HttpObjectAggregator(8192);
        ctx.pipeline().addBefore("websockethandler", "aggregator", handler);
        ctx.pipeline()
           .addAfter("aggregator",
                     "websocketx",
                     new WebSocketServerProtocolHandler(websocketDispatcher.getWebsocketUri(), "xmpp", true));
        ctx.pipeline().remove("idler");
        ctx.pipeline().remove("compressor");
        handler.channelRead(ctx, msg);
    }

    private boolean isWebsocketRequest(ChannelHandlerContext ctx, HttpRequest req) {
        if (websocketDispatcher == null || req.getUri() == null) {
            return false;
        }

        return req.getUri().startsWith(websocketDispatcher.getWebsocketUri());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy