package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket;


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.filter.NettyUdpServerPermeateServerRealFilter;

import java.util.concurrent.TimeUnit;

/**
 * 服务端渗透服务端 连接真实通道
 */
@Slf4j
public class NettyUdpServerPermeateServerConnectRealSocket {
    private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

    /**
     * 连接真实服务
     *
     * @param internalNetworkServerPermeateServerRealServer 访客信息
     */
    public static void buildRealServer(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer, Channel visitorChannel , String visitorId) {
        buildNewRealServer(internalNetworkServerPermeateServerRealServer,visitorChannel,visitorId);
    }

    /**
     * @param internalNetworkServerPermeateServerRealServer 访客信息
     * @param visitorChannel
     * @param visitorId
     */
    private static void buildNewRealServer(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer,
                                           Channel visitorChannel, String visitorId) {
        try {
            String clientTargetIp = internalNetworkServerPermeateServerRealServer.getClientTargetIp();
            Integer clientTargetPort = internalNetworkServerPermeateServerRealServer.getClientTargetPort();
            Integer visitorPort = internalNetworkServerPermeateServerRealServer.getVisitorPort();
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
//                     设置读缓冲区为2M
                    .option(ChannelOption.SO_RCVBUF, 2048 * 1024)
//                     设置写缓冲区为1M
                    .option(ChannelOption.SO_SNDBUF, 1024 * 1024)
//                    .option(ChannelOption.TCP_NODELAY, false)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
//                    .option(ChannelOption.SO_BACKLOG, 128)//务端接受连接的队列长度 默认128
//                    .option(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认AdaptiveRecvByteBufAllocator.DEFAULT
                    .option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))
                    .handler(new NettyUdpServerPermeateServerRealFilter(internalNetworkServerPermeateServerRealServer))

            ;


            bootstrap
                    .connect(clientTargetIp, clientTargetPort)
                    .sync()
                    .addListener((ChannelFutureListener) channelFuture -> {
                        if (channelFuture.isSuccess()) {
                            // 客户端链接真实服务成功 设置自动读写false 等待访客连接成功后设置成true
                            Channel realChannel = channelFuture.channel();
                            realChannel.config().setOption(ChannelOption.AUTO_READ, false);

                            log.info("服务端内网渗透通过,绑定本地服务,IP:{},端口:{} channelID:{} 新建通道成功", clientTargetIp, clientTargetPort,realChannel.id().asLongText());
                            ChannelAttributeKeyUtils.buildVisitorPort(realChannel, visitorPort);
                            // 缓存当前端口对应的通道、通道池
                            ChannelAttributeKeyUtils.buildNextChannel(realChannel, visitorChannel);
                            ChannelAttributeKeyUtils.buildNextChannel(visitorChannel, realChannel);

                            ChannelAttributeKeyUtils.buildVisitorId(realChannel, visitorId);

                            visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);

                        } else {
                            log.error("服务端内网渗透 无法连接当前网络内的目标IP：【{}】,目标端口:【{}】", clientTargetIp, clientTargetPort);
                            eventLoopGroup.schedule(() -> {
                                buildNewRealServer(internalNetworkServerPermeateServerRealServer, visitorChannel, visitorId);
                            }, 2, TimeUnit.SECONDS);
                        }
            });


        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}