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

com.fastchar.socket.server.websocket.FastWebSocketServerChannelHandler Maven / Gradle / Ivy

package com.fastchar.socket.server.websocket;

import com.fastchar.core.FastChar;
import com.fastchar.socket.core.FastWebSocket;
import com.fastchar.socket.interfaces.IFastWebSocketServerListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.*;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author 沈建(Janesen)
 * @date 2021/3/31 09:31
 */
public class FastWebSocketServerChannelHandler extends SimpleChannelInboundHandler {
    private static final ConcurrentMap FAST_WEB_SOCKET_CONCURRENT_MAP = new ConcurrentHashMap<>();

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        ctx.close();
        notifyClose(ctx, cause);
    }

    private void notifyClose(ChannelHandlerContext ctx, Throwable cause) {
        List iFastWebSocketByTexts = FastChar.getOverrides().singleInstances(false, IFastWebSocketServerListener.class);
        for (IFastWebSocketServerListener iFastWebSocketByText : iFastWebSocketByTexts) {
            if (iFastWebSocketByText == null) {
                continue;
            }
            iFastWebSocketByText.onClose(FAST_WEB_SOCKET_CONCURRENT_MAP.get(ctx.channel().id().asShortText()), cause, -1);
        }
        FAST_WEB_SOCKET_CONCURRENT_MAP.remove(ctx.channel().id().asShortText());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        notifyClose(ctx, null);
    }

    @Override
    protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
            handleHttpRequest(ctx, (FullHttpRequest) msg);
        } else if (msg instanceof WebSocketFrame) {
            handleWebSocketFrame(ctx, (WebSocketFrame) msg);
        }
    }

    private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
        if (!req.decoderResult().isSuccess() || (!"websocket".contentEquals(req.headers().get("Upgrade")))) {
            return;
        }
        String socketUrl = "ws://" + req.headers().get("host") + req.uri();
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(socketUrl, null, false);
        WebSocketServerHandshaker handShaker = wsFactory.newHandshaker(req);
        if (handShaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
        } else {
            FastWebSocket webSocket = new FastWebSocket(ctx.channel(), req.uri());
            handShaker.handshake(ctx.channel(), req);
            FAST_WEB_SOCKET_CONCURRENT_MAP.put(ctx.channel().id().asShortText(), webSocket);
            List iFastWebSocketByTexts = FastChar.getOverrides().singleInstances(false, IFastWebSocketServerListener.class);
            for (IFastWebSocketServerListener iFastWebSocketByText : iFastWebSocketByTexts) {
                if (iFastWebSocketByText == null) {
                    continue;
                }
                iFastWebSocketByText.onOpen(webSocket, req);
            }
        }
    }

    private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        List iFastWebSocketByTexts = FastChar.getOverrides().singleInstances(false, IFastWebSocketServerListener.class);
        if (frame instanceof CloseWebSocketFrame) {
            for (IFastWebSocketServerListener iFastWebSocketByText : iFastWebSocketByTexts) {
                if (iFastWebSocketByText == null) {
                    continue;
                }
                iFastWebSocketByText.onClose(FAST_WEB_SOCKET_CONCURRENT_MAP.get(ctx.channel().id().asShortText()), null, 0);
            }
            return;
        }
        if (frame instanceof TextWebSocketFrame) {
            TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) frame;
            for (IFastWebSocketServerListener iFastWebSocketByText : iFastWebSocketByTexts) {
                if (iFastWebSocketByText == null) {
                    continue;
                }
                iFastWebSocketByText.onMessage(FAST_WEB_SOCKET_CONCURRENT_MAP.get(ctx.channel().id().asShortText()), textWebSocketFrame.text());
            }
        } else if (frame instanceof PingWebSocketFrame) {
            ctx.channel().writeAndFlush(new PongWebSocketFrame());
        } else if (frame instanceof PongWebSocketFrame) {
            ctx.channel().writeAndFlush(new PingWebSocketFrame());
        }
    }

}