private void read(SocketSessionImpl session) {
        ByteBuffer buf = ByteBuffer.allocate(session.getReadBufferSize());
        SocketChannel ch = session.getChannel();

        try {
            int readBytes = 0;
            int ret;

            try {
                while ((ret = ch.read(buf.buf())) > 0) {
                    readBytes += ret;
                }
            } finally {
                buf.flip();
            }

            session.increaseReadBytes(readBytes);

            if (readBytes > 0) {
                session.getFilterChain().fireMessageReceived(session, buf);
                buf = null;

                if (readBytes * 2 < session.getReadBufferSize()) {
                    session.decreaseReadBufferSize();
                } else if (readBytes == session.getReadBufferSize()) {
                    session.increaseReadBufferSize();
                }
            }
            if (ret < 0) {
                scheduleRemove(session);
            }
        } catch (Throwable e) {
            if (e instanceof IOException)
                scheduleRemove(session);
            session.getFilterChain().fireExceptionCaught(session, e);
        } finally {
            if (buf != null)
                buf.release();
        }
    }