diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameEncoder.java index 28332d2fdd..814d087122 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameEncoder.java @@ -16,9 +16,12 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageEncoder; + +import java.util.List; /** * Encodes a {@link WebSocketFrame} into a {@link ByteBuf}. @@ -27,56 +30,71 @@ import io.netty.handler.codec.MessageToByteEncoder; * WebSocketServer example located in the {@code io.netty.example.http.websocket} package. */ @Sharable -public class WebSocket00FrameEncoder extends MessageToByteEncoder implements WebSocketFrameEncoder { +public class WebSocket00FrameEncoder extends MessageToMessageEncoder implements WebSocketFrameEncoder { + private static final ByteBuf _0X00 = Unpooled.unreleasableBuffer( + Unpooled.directBuffer(1, 1).writeByte((byte) 0x00)); + private static final ByteBuf _0XFF = Unpooled.unreleasableBuffer( + Unpooled.directBuffer(1, 1).writeByte((byte) 0xFF)); + private static final ByteBuf _0XFF_0X00 = Unpooled.unreleasableBuffer( + Unpooled.directBuffer(2, 2).writeByte((byte) 0xFF).writeByte((byte) 0x00)); @Override - protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, ByteBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List out) throws Exception { if (msg instanceof TextWebSocketFrame) { // Text frame ByteBuf data = msg.content(); - out.writeByte((byte) 0x00); - out.writeBytes(data, data.readerIndex(), data.readableBytes()); - out.writeByte((byte) 0xFF); + + out.add(_0X00.duplicate()); + out.add(data.retain()); + out.add(_0XFF.duplicate()); } else if (msg instanceof CloseWebSocketFrame) { // Close frame - out.writeByte((byte) 0xFF); - out.writeByte((byte) 0x00); + out.add(_0XFF_0X00); } else { // Binary frame ByteBuf data = msg.content(); int dataLen = data.readableBytes(); - out.ensureWritable(dataLen + 5); - // Encode type. - out.writeByte((byte) 0x80); + ByteBuf buf = ctx.alloc().buffer(5); + boolean release = true; + try { + // Encode type. + buf.writeByte((byte) 0x80); - // Encode length. - int b1 = dataLen >>> 28 & 0x7F; - int b2 = dataLen >>> 14 & 0x7F; - int b3 = dataLen >>> 7 & 0x7F; - int b4 = dataLen & 0x7F; - if (b1 == 0) { - if (b2 == 0) { - if (b3 == 0) { - out.writeByte(b4); + // Encode length. + int b1 = dataLen >>> 28 & 0x7F; + int b2 = dataLen >>> 14 & 0x7F; + int b3 = dataLen >>> 7 & 0x7F; + int b4 = dataLen & 0x7F; + if (b1 == 0) { + if (b2 == 0) { + if (b3 == 0) { + buf.writeByte(b4); + } else { + buf.writeByte(b3 | 0x80); + buf.writeByte(b4); + } } else { - out.writeByte(b3 | 0x80); - out.writeByte(b4); + buf.writeByte(b2 | 0x80); + buf.writeByte(b3 | 0x80); + buf.writeByte(b4); } } else { - out.writeByte(b2 | 0x80); - out.writeByte(b3 | 0x80); - out.writeByte(b4); + buf.writeByte(b1 | 0x80); + buf.writeByte(b2 | 0x80); + buf.writeByte(b3 | 0x80); + buf.writeByte(b4); } - } else { - out.writeByte(b1 | 0x80); - out.writeByte(b2 | 0x80); - out.writeByte(b3 | 0x80); - out.writeByte(b4); - } - // Encode binary data. - out.writeBytes(data, data.readerIndex(), dataLen); + // Encode binary data. + out.add(buf); + out.add(data.retain()); + release = false; + } finally { + if (release) { + buf.release(); + } + } } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.java index bd95696afe..19ee9d0787 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.java @@ -56,12 +56,13 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.TooLongFrameException; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.nio.ByteBuffer; +import java.util.List; /** *

@@ -69,7 +70,7 @@ import java.nio.ByteBuffer; * href="https://github.com/joewalnes/webbit">webbit and modified. *

*/ -public class WebSocket08FrameEncoder extends MessageToByteEncoder implements WebSocketFrameEncoder { +public class WebSocket08FrameEncoder extends MessageToMessageEncoder implements WebSocketFrameEncoder { private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocket08FrameEncoder.class); @@ -94,7 +95,7 @@ public class WebSocket08FrameEncoder extends MessageToByteEncoder out) throws Exception { byte[] mask; @@ -138,38 +139,61 @@ public class WebSocket08FrameEncoder extends MessageToByteEncoder>> 8 & 0xFF); - out.writeByte(length & 0xFF); - } else { - out.ensureWritable(10 + maskLength + length); - out.writeByte(b0); - out.writeByte(maskPayload ? 0xFF : 127); - out.writeLong(length); - } - - // Write payload - if (maskPayload) { - int random = (int) (Math.random() * Integer.MAX_VALUE); - mask = ByteBuffer.allocate(4).putInt(random).array(); - out.writeBytes(mask); - - int counter = 0; - for (int i = data.readerIndex(); i < data.writerIndex(); i ++) { - byte byteData = data.getByte(i); - out.writeByte(byteData ^ mask[counter++ % 4]); + boolean release = true; + ByteBuf buf = null; + try { + int maskLength = maskPayload ? 4 : 0; + if (length <= 125) { + int size = 2 + maskLength; + if (maskPayload) { + size += length; + } + buf = ctx.alloc().buffer(size); + buf.writeByte(b0); + byte b = (byte) (maskPayload ? 0x80 | (byte) length : (byte) length); + buf.writeByte(b); + } else if (length <= 0xFFFF) { + int size = 4 + maskLength; + if (maskPayload) { + size += length; + } + buf = ctx.alloc().buffer(size); + buf.writeByte(b0); + buf.writeByte(maskPayload ? 0xFE : 126); + buf.writeByte(length >>> 8 & 0xFF); + buf.writeByte(length & 0xFF); + } else { + int size = 10 + maskLength; + if (maskPayload) { + size += length; + } + buf = ctx.alloc().buffer(size); + buf.writeByte(b0); + buf.writeByte(maskPayload ? 0xFF : 127); + buf.writeLong(length); + } + + // Write payload + if (maskPayload) { + int random = (int) (Math.random() * Integer.MAX_VALUE); + mask = ByteBuffer.allocate(4).putInt(random).array(); + buf.writeBytes(mask); + + int counter = 0; + for (int i = data.readerIndex(); i < data.writerIndex(); i ++) { + byte byteData = data.getByte(i); + buf.writeByte(byteData ^ mask[counter++ % 4]); + } + out.add(buf); + } else { + out.add(buf); + out.add(data.retain()); + } + release = false; + } finally { + if (release && buf != null) { + buf.release(); } - } else { - out.writeBytes(data, data.readerIndex(), data.readableBytes()); } } }