// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/core/Connection.java
// public class Connection {
// 
//     private ChannelHandlerContext chc;
// 
//     public void send(Packet packet) {
//         chc.channel().writeAndFlush(packet);
//     }
// 
//     public ChannelHandlerContext getChc() {
//         return chc;
//     }
// 
//     public void setChc(ChannelHandlerContext chc) {
//         this.chc = chc;
//     }
// }
// 
// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/core/PacketReceiver.java
// public final class PacketReceiver {
// 
//     private static final Logger logger = LoggerFactory.getLogger(PacketReceiver.class);
//     private static List<Filter> filterList = new ArrayList<>();
//     private static final Map<Command, PacketHandler> handlers = new HashMap<>();
// 
//     public void addHandler(PacketHandler handler) {
//         logger.debug("register : {}", handler.cmd().name());
//         handlers.put(handler.cmd(), handler);
//     }
// 
//     public void addFilter(Filter filter) {
//         logger.debug("filter : {}", filter.getClass());
//         filterList.add(filter);
//     }
// 
//     public void onReceive(Packet packet, Connection connection) {
//         Command command = Command.toCMD(packet.getCmd());
//         PacketHandler handler = handlers.get(command);
//         logger.debug("new packet : {}", command);
//         if (handler == null) return;
//         for (Filter filter : filterList) {
//             if (filter.exec(packet, connection).equals(FilterResult.END)) return;
//         }
//         try {
//             handler.handle(packet, connection);
//         } catch (Throwable e) {
//             e.printStackTrace();
//         }
//     }
// }
// 
// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/dto/Packet.java
// @Message
// public class Packet {
// 
//     private byte cmd; // 命令
//     private short cc; // 校验码 暂时没有用到
//     private byte flags; // 特性，如是否加密，是否压缩等
//     private String sessionId; // 会话id。客户端生成。
//     private byte lrc; // 校验，纵向冗余校验。只校验head
//     private byte[] body;
// 
// 
//     public Packet(byte cmd) {
//         this.cmd = cmd;
//     }
// 
//     public Packet() {
//     }
// 
//     public Packet(byte cmd, String sessionId) {
//         this.cmd = cmd;
//         this.sessionId = sessionId;
//     }
// 
//     public Packet(Command cmd) {
//         this.cmd = cmd.cmd;
//     }
// 
//     public Packet(Command cmd, String sessionId) {
//         this.cmd = cmd.cmd;
//         this.sessionId = sessionId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{" + "cmd=" + cmd + ", cc=" + cc + ", flags=" + flags + ", sessionId=" + sessionId + ", lrc=" + lrc
//                 + ", body=" + (body == null ? 0 : body.length) + '}';
//     }
// 
//     public byte getCmd() {
//         return cmd;
//     }
// 
//     public void setCmd(byte cmd) {
//         this.cmd = cmd;
//     }
// 
//     public short getCc() {
//         return cc;
//     }
// 
//     public void setCc(short cc) {
//         this.cc = cc;
//     }
// 
//     public byte getFlags() {
//         return flags;
//     }
// 
//     public void setFlags(byte flags) {
//         this.flags = flags;
//     }
// 
//     public String getSessionId() {
//         return sessionId;
//     }
// 
//     public void setSessionId(String sessionId) {
//         this.sessionId = sessionId;
//     }
// 
//     public byte getLrc() {
//         return lrc;
//     }
// 
//     public void setLrc(byte lrc) {
//         this.lrc = lrc;
//     }
// 
//     public byte[] getBody() {
//         return body;
//     }
// 
//     public void setBody(byte[] body) {
//         this.body = body;
//     }
// }


import cn.ctodb.push.core.Connection;
import cn.ctodb.push.core.PacketReceiver;
import cn.ctodb.push.dto.Packet;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
package cn.ctodb.push.server;


// 服务端消息处理统一入口
@Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
    private Logger logger = LoggerFactory.getLogger(ServerHandler.class);
    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private PacketReceiver packetReceiver;

    public ServerHandler(PacketReceiver packetReceiver) {
        this.packetReceiver = packetReceiver;
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) { // (2)
        Channel incoming = ctx.channel();
        logger.debug("handlerAdded : {}", incoming.remoteAddress());
        channels.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) { // (3)
        Channel incoming = ctx.channel();
        logger.debug("handlerRemoved : {}", incoming.remoteAddress());
        channels.remove(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // (4)
        Packet packet = (Packet) msg;
// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/core/Connection.java
// public class Connection {
// 
//     private ChannelHandlerContext chc;
// 
//     public void send(Packet packet) {
//         chc.channel().writeAndFlush(packet);
//     }
// 
//     public ChannelHandlerContext getChc() {
//         return chc;
//     }
// 
//     public void setChc(ChannelHandlerContext chc) {
//         this.chc = chc;
//     }
// }
// 
// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/core/PacketReceiver.java
// public final class PacketReceiver {
// 
//     private static final Logger logger = LoggerFactory.getLogger(PacketReceiver.class);
//     private static List<Filter> filterList = new ArrayList<>();
//     private static final Map<Command, PacketHandler> handlers = new HashMap<>();
// 
//     public void addHandler(PacketHandler handler) {
//         logger.debug("register : {}", handler.cmd().name());
//         handlers.put(handler.cmd(), handler);
//     }
// 
//     public void addFilter(Filter filter) {
//         logger.debug("filter : {}", filter.getClass());
//         filterList.add(filter);
//     }
// 
//     public void onReceive(Packet packet, Connection connection) {
//         Command command = Command.toCMD(packet.getCmd());
//         PacketHandler handler = handlers.get(command);
//         logger.debug("new packet : {}", command);
//         if (handler == null) return;
//         for (Filter filter : filterList) {
//             if (filter.exec(packet, connection).equals(FilterResult.END)) return;
//         }
//         try {
//             handler.handle(packet, connection);
//         } catch (Throwable e) {
//             e.printStackTrace();
//         }
//     }
// }
// 
// Path: cn.ctodb.push.core/src/main/java/cn/ctodb/push/dto/Packet.java
// @Message
// public class Packet {
// 
//     private byte cmd; // 命令
//     private short cc; // 校验码 暂时没有用到
//     private byte flags; // 特性，如是否加密，是否压缩等
//     private String sessionId; // 会话id。客户端生成。
//     private byte lrc; // 校验，纵向冗余校验。只校验head
//     private byte[] body;
// 
// 
//     public Packet(byte cmd) {
//         this.cmd = cmd;
//     }
// 
//     public Packet() {
//     }
// 
//     public Packet(byte cmd, String sessionId) {
//         this.cmd = cmd;
//         this.sessionId = sessionId;
//     }
// 
//     public Packet(Command cmd) {
//         this.cmd = cmd.cmd;
//     }
// 
//     public Packet(Command cmd, String sessionId) {
//         this.cmd = cmd.cmd;
//         this.sessionId = sessionId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{" + "cmd=" + cmd + ", cc=" + cc + ", flags=" + flags + ", sessionId=" + sessionId + ", lrc=" + lrc
//                 + ", body=" + (body == null ? 0 : body.length) + '}';
//     }
// 
//     public byte getCmd() {
//         return cmd;
//     }
// 
//     public void setCmd(byte cmd) {
//         this.cmd = cmd;
//     }
// 
//     public short getCc() {
//         return cc;
//     }
// 
//     public void setCc(short cc) {
//         this.cc = cc;
//     }
// 
//     public byte getFlags() {
//         return flags;
//     }
// 
//     public void setFlags(byte flags) {
//         this.flags = flags;
//     }
// 
//     public String getSessionId() {
//         return sessionId;
//     }
// 
//     public void setSessionId(String sessionId) {
//         this.sessionId = sessionId;
//     }
// 
//     public byte getLrc() {
//         return lrc;
//     }
// 
//     public void setLrc(byte lrc) {
//         this.lrc = lrc;
//     }
// 
//     public byte[] getBody() {
//         return body;
//     }
// 
//     public void setBody(byte[] body) {
//         this.body = body;
//     }
// }


// Path: cn.ctodb.push.server/src/main/java/cn/ctodb/push/server/ServerHandler.java
import cn.ctodb.push.core.Connection;
import cn.ctodb.push.core.PacketReceiver;
import cn.ctodb.push.dto.Packet;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

package cn.ctodb.push.server;


// 服务端消息处理统一入口
@Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
    private Logger logger = LoggerFactory.getLogger(ServerHandler.class);
    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private PacketReceiver packetReceiver;

    public ServerHandler(PacketReceiver packetReceiver) {
        this.packetReceiver = packetReceiver;
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) { // (2)
        Channel incoming = ctx.channel();
        logger.debug("handlerAdded : {}", incoming.remoteAddress());
        channels.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) { // (3)
        Channel incoming = ctx.channel();
        logger.debug("handlerRemoved : {}", incoming.remoteAddress());
        channels.remove(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // (4)
        Packet packet = (Packet) msg;
        Connection connection = new Connection();