netty: Как отредактировать внутренний массив bytebuf на месте? - PullRequest
0 голосов
/ 25 июня 2018

В моем случае использования мне нужно xor каждый байт перед чтением или записью в сеть.Поэтому для этого я реализую дуплексный обработчик.

Но странно, что я не смог отредактировать выходной байтбуф на месте, в то время как сторона чтения могла бы:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    ByteBuf buf = (ByteBuf) msg;
    ByteBuf res = buf.alloc().buffer(buf.readableBytes());
    buf.forEachByte(value -> {
        res.writeByte(value ^ cookie);
        return true;
    });
    buf.release();
    super.write(ctx, res, promise);
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    ByteBuf buf = (ByteBuf) msg;
    buf.forEachByte(new ByteProcessor() {
        private int i = 0;

        @Override
        public boolean process(byte value) throws Exception {
            buf.setByte(i++, value ^ cookie);
            return true;
        }
    });
    super.channelRead(ctx, msg);
}

Обратите внимание, что параметр msgwrite() обеспечивается в типе ByteBuf из предыдущего обработчика.

Если я отредактирую bytebuf на месте в write(), приложение не сможет работать должным образом (я не знаю, что произойдет,мое приложение является прокси-программой, и если я отредактирую buf на месте, оно не будет работать: какое-то прокси-соединение даст неверный контент), поэтому я вынужден отступить, чтобы скопировать буфер для редактирования, что является медленным способом, верно?

Есть ли что-то особенное в bytebuf в write()?

Редактировать:

Прокси-сервер обрабатывает два канала как пару, входящий канали исходящий канал, и данные прокси между ними.

конвейер входящего канала:

ch.pipeline().addLast("ReadTimeoutHandler", new ReadTimeoutHandler(30));
ch.pipeline().addLast("WriteTimeoutHandler", new WriteTimeoutHandler(30));
cookie.ifPresent(c -> ch.pipeline().addLast(new FuzzHandler(c)));
ch.pipeline().addLast(new CopyHandler());

конвейер исходящего канала:

ch.pipeline().addLast(new CopyHandler());

CopyHandler будет write() сопряженный канал друг с другом.

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Я нашел проблему.

В некотором пути моих кодов я Unpooled.wrappedBuffer() статический байтовый массив и делаю write(), поэтому, если write() в исходящем обработчике изменяет буфер напрямую, это изменит байтовый массив и повлияет на следующее повторное использование, таким образом, контент, записанный в сеть, в половину раза неверен.

Итак, решение - скопировать байтовый массив:

ByteBuf buf = ctx.alloc().buffer(src.length);
buf.writeBytes(src);

Кстати, как правильно изменить буфер на месте? setByte() следует использовать readerIndex в качестве смещения?

ByteBuf buf = (ByteBuf) msg;
final int readerIndex = buf.readerIndex();
buf.forEachByte(new ByteProcessor() {
    private int i = 0;

    @Override
    public boolean process(byte value) throws Exception {
        buf.setByte(readerIndex + i, value ^ cookie);
        i++;
        return true;
    }
});
0 голосов
/ 25 июня 2018

В общем, должна быть возможность отрегулировать его на месте. Я подозреваю, что у вас могут возникнуть проблемы, когда вы пишете один и тот же буфер несколько раз (или разные буферы, которые совместно используют одно и то же хранилище).

...