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

com.neko233.socket233.impl.websocket.handler.HttpUpgradeToWebsocketProtocolHandler Maven / Gradle / Ivy

The newest version!
package com.neko233.socket233.impl.websocket.handler;

import com.neko233.socket233.core.NetworkEngine;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

/**
 * HTTP --> ws 协议
 *
 * @author SolarisNeko
 * Date on 2022-12-16
 */
@Slf4j
public class HttpUpgradeToWebsocketProtocolHandler extends ChannelInboundHandlerAdapter {

    private final NetworkEngine networkEngine;
    WebSocketServerHandshaker handShaker;

    public HttpUpgradeToWebsocketProtocolHandler(NetworkEngine networkEngine) {
        this.networkEngine = networkEngine;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {


        if (!(msg instanceof HttpRequest)) {
            log.error("Incoming request is unknown");
            return;
        }

        HttpRequest httpRequest = (HttpRequest) msg;

        HttpHeaders headers = httpRequest.headers();
//        log.debug("Connection : " + headers.get("Connection"));
//        log.debug("Upgrade : " + headers.get("Upgrade"));

        // connection & upgrade
        if ("Upgrade".equalsIgnoreCase(headers.get(HttpHeaderNames.CONNECTION))
                && "WebSocket".equalsIgnoreCase(headers.get(HttpHeaderNames.UPGRADE))
        ) {

            // Adding new handler to the existing pipeline to handle WebSocket Messages
            WebsocketProtocolHandler wsHandler = new WebsocketProtocolHandler(networkEngine);
            ctx.pipeline()
                    .replace(this, "websocketHandler", wsHandler);

            wsHandler.channelRegistered(ctx);

            // WebSocketHandler added to the pipeline. replace httpServerHandler
            this.handleWebsocketHandshake(ctx, httpRequest);

            // Handshake is done


        } else {
            InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
            String ip = remoteAddress.getAddress().getHostAddress();
            int port = remoteAddress.getPort();
            log.error("[HttpServerHandler] Remote request not a HTTP for websocket connection. ip ={}, port = {} "
                    , ip, port);
            return;
        }


    }


    /**
     * Do the handshaking for WebSocket request
     */
    protected void handleWebsocketHandshake(ChannelHandlerContext ctx, HttpRequest req) {
        String wsUrl = getWebSocketURL(req);
        log.debug("request websocket URL = {}", wsUrl);

        WebSocketServerHandshakerFactory wsFactory =
                new WebSocketServerHandshakerFactory(wsUrl, null, true);
        // 握手
        handShaker = wsFactory.newHandshaker(req);
        if (handShaker == null) {
            // 不支持该版本
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
        } else {
            handShaker.handshake(ctx.channel(), req);
        }
    }

    protected String getWebSocketURL(HttpRequest req) {
        return "ws://" + req.headers().get("Host") + req.uri();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy