class Socks5AcceptorHandler extends IoHandlerAdapter {

    public void messageReceived(final IoSession session, Object message) throws Exception {
        IoBuffer buffer = (IoBuffer) message;

        ProxyState state = getState(session);

        try {
            if (state == ProxyState.OPENED) {
                OpeningPacket packet = new OpeningPacket(buffer);

                if (packet.isAuthSupported()) {
                    // no auth
                    setState(session, ProxyState.INITIATED);
                    session.write(packet.createResponse());
                    log.info("SOCKS5 session initiated");
                } else {
                    // not supported
                    session.write(packet.createResponse());
                    session.close(false);
                    log.info("SOCKS5 session closed");
                }

            } else if (state == ProxyState.INITIATED) {
                InitiatingPacket packet = new InitiatingPacket(buffer);

                session.write(packet.createResponse());
                setState(session, ProxyState.CONNECTED);

                String hash = packet.getAddress();
                Socks5Pair pair = connections.register(hash, session);

                session.setAttribute(PAIR_KEY, pair);
            } else {
                Socks5Pair pair = getPair(session);
                if (pair != null && pair.isActivated()) {
                    pair.getOther(session).write(message);
                } else {
                    // writing before activated, close
                    pair.close();
                }
            }
        } catch (IllegalArgumentException e) {
            session.close(false);
            log.info("SOCKS5 session closed");
        }
    }

    public  Socks5AcceptorHandler(Socks5ConnectionsRegistry connections);

}