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

com.neko233.socket233.impl.websocket.NetworkEngineByWebsocketNetty Maven / Gradle / Ivy

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

import com.neko233.socket233.core.NetworkEngine;
import com.neko233.socket233.core.common.Kv;
import com.neko233.socket233.core.engine.exception.EngineStartUpException;
import com.neko233.socket233.core.utils.ResourcesJdkUtils;
import com.neko233.socket233.impl.websocket.pipeline.WebSocketConfigChannelInitializer;
import com.neko233.socket233.netty.NettyServerCreateResult;
import com.neko233.socket233.netty.NettyServerUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import javax.net.ssl.SSLException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.BindException;
import java.security.cert.CertificateException;
import java.util.Properties;


@Slf4j
public class NetworkEngineByWebsocketNetty implements NetworkEngine {

    @Override
    public void init() throws Throwable {

    }

    @Override
    public void create() throws Throwable {

        // other thread run
        Thread wsThread = new Thread(() -> {
            log.info("websocket Netty Server is going to start up.");
            try {
                startUpNettyWebsocket();
            } catch (Exception e) {
                handleStartUpException(e);
            }
            log.info("websocket Netty Server is started");
        });
        wsThread.setName("websocket-netty-server-thread-main");
        wsThread.start();
    }

    private void startUpNettyWebsocket() throws CertificateException, SSLException {

        checkConfigKv();
        final Boolean isHaveSsl = getConfigKv().getBoolean("server.isHaveSsl");
        final Integer port = getPort();

        // Configure SSL.
        final SslContext sslCtx;
        if (isHaveSsl) {
            SelfSignedCertificate ssc = new SelfSignedCertificate();
            sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        } else {
            sslCtx = null;
        }


        // Configure the server.
        WebSocketConfigChannelInitializer channelInitializer = new WebSocketConfigChannelInitializer(this);
        NettyServerCreateResult result = NettyServerUtils.getNettyServerCreateResult(channelInitializer);
        ServerBootstrap serverBootstrap = result.serverBootstrap;
        EventLoopGroup bossGroup = result.bossGroup;
        EventLoopGroup workerGroup = result.workerGroup;

        try {


            final Channel ch = serverBootstrap.bind(port)
                    .sync()
                    .channel();

            log.info("启动 websocket server 成功! port = {}", port);

            logServerStartupSuccess(serverBootstrap);

            ch.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("启动 netty websocket 失败", e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }


    private static void logServerStartupSuccess(ServerBootstrap serverBootstrap) {
        serverBootstrap.config().options().get(ChannelOption.MAX_MESSAGES_PER_WRITE);

    }

    @Override
    public void destroy() {

    }

    @Override
    public void shutdown() {

    }

    @Override
    public Kv getConfigKv() {
        String configFilePath = getConfigFilePath();
        Kv kv = new Kv();
        try {
            File resourceConfigFile;
            if (configFilePath.startsWith("absolute:")) {
                // 绝对路径协议
                String filePath = configFilePath.replaceFirst("absolute:", "");
                resourceConfigFile = new File(filePath);
            } else {
                // 默认, resources/ 目录下
                resourceConfigFile = ResourcesJdkUtils.getResourceFile(configFilePath);
            }
            if (resourceConfigFile == null) {
                return kv;
            }

            // 不存在
            if (!resourceConfigFile.exists()) {
                log.error("配置文件不存在! file full path = {}", resourceConfigFile.getAbsolutePath());
                return kv;
            }

            // properties 读取
            final Properties properties = new Properties();
            properties.load(new FileReader(resourceConfigFile));
            properties.forEach((k, v) -> {
                kv.put(String.valueOf(k), String.valueOf(v));
            });
            return kv;
        } catch (IOException e) {
            log.error("read config file error.", e);
            return kv;
        }
    }


    @Override
    public void handleStartUpException(Throwable e) {
        if (e instanceof BindException) {
            String msg = String.format("启动 NettyWebsocketNetworkEngine 报错. port 被占用 = %s",
                    this.getPort());
            throw new EngineStartUpException(e, msg);
        }
        throw new EngineStartUpException(e, "启动 NettyWebsocketNetworkEngine 报错. 没匹配到错误原因");
    }

    @Override
    public Logger getLogger() {
        return log;
    }

    @Override
    public String getEngineName() {
        return "netty-websocket";
    }

    @Override
    public void checkConfigKv() {
        final Integer port = getConfigKv().getInt("server.port");
        if (port == null) {
            log.error("port is null!");
            throw new IllegalArgumentException();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy