package com.wecloud.im.netty.core;

import com.wecloud.im.ws.model.WsConstants;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class NettyChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Resource
    private ChannelInboundHandler channelInboundHandler;

    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();
        // http
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpObjectAggregator(2048576000));

        // 服务端api接口
        pipeline.addLast("SingleHttpRequestHandler", channelInboundHandler);

        // 连接超时管理 (判断通道是否有数据写入)
        pipeline.addLast("readTimeoutHandler", new ReadTimeoutHandler(60));

        // "/appws"路径 升级长连接
        pipeline.addLast("appWebSocketServerotocolHandler", new WebSocketServerProtocolHandler(WsConstants.WS_URL));

        /*
         * 心跳机制
         * observeOutput -当评估写空闲时是否应该考虑字节的消耗。默认为false。
         * readerIdleTime—状态为IdleState的IdleStateEvent。当在指定的时间内没有执行读操作时，将触发READER_IDLE。指定0禁用。
         * writerIdleTime—状态为IdleState的IdleStateEvent。当在指定的时间内没有执行写操作时，会触发WRITER_IDLE。指定0禁用。
         * allIdleTime—状态为IdleState的IdleStateEvent。在一定时间内不读不写会触发ALL_IDLE。指定0禁用。
         * unit—readerIdleTime、writeIdleTime和allIdleTime的时间单位
         */
        pipeline.addLast(new IdleStateHandler(2, 2, 10, TimeUnit.SECONDS));
    }

}
