@Override public void write(ByteBuf bb, OFFlowStatsEntryVer10 message) { int startIndex = bb.writerIndex(); // length is length of variable message, will be updated at the end int lengthIndex = bb.writerIndex(); bb.writeShort(U16.t(0)); message.tableId.writeByte(bb); // pad: 1 bytes bb.writeZero(1); message.match.writeTo(bb); bb.writeInt(U32.t(message.durationSec)); bb.writeInt(U32.t(message.durationNsec)); bb.writeShort(U16.t(message.priority)); bb.writeShort(U16.t(message.idleTimeout)); bb.writeShort(U16.t(message.hardTimeout)); // pad: 6 bytes bb.writeZero(6); bb.writeLong(message.cookie.getValue()); bb.writeLong(message.packetCount.getValue()); bb.writeLong(message.byteCount.getValue()); ChannelUtils.writeList(bb, message.actions); // update length field int length = bb.writerIndex() - startIndex; bb.setShort(lengthIndex, length); }
@Override protected int doReadMessages(List<Object> buf) throws Exception { SctpChannel ch = javaChannel(); RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle(); ByteBuf buffer = allocHandle.allocate(config().getAllocator()); boolean free = true; try { ByteBuffer data = buffer.internalNioBuffer(buffer.writerIndex(), buffer.writableBytes()); int pos = data.position(); MessageInfo messageInfo = ch.receive(data, null, notificationHandler); if (messageInfo == null) { return 0; } buf.add( new SctpMessage( messageInfo, buffer.writerIndex(buffer.writerIndex() + data.position() - pos))); free = false; return 1; } catch (Throwable cause) { PlatformDependent.throwException(cause); return -1; } finally { int bytesRead = buffer.readableBytes(); allocHandle.record(bytesRead); if (free) { buffer.release(); } } }
@Override protected void encode(ChannelHandlerContext ctx, TransportFrame frame, ByteBuf out) throws Exception { out.writeByte('E'); out.writeByte('Q'); out.writeInt(frame.version().id); out.writeLong(frame.request()); if (frame instanceof StreamableTransportFrame) { // message request // skip size header int sizePos = out.writerIndex(); out.writerIndex(out.writerIndex() + 4); try (StreamOutput output = streamService.output(out)) { Streamable message = ((StreamableTransportFrame) frame).message(); output.writeClass(message.getClass()); output.writeStreamable(message); } int size = out.writerIndex() - sizePos - 4; out.setInt(sizePos, size); } else { // ping request out.writeInt(0); } }
@Override protected int doReadMessages(MessageBuf<Object> buf) throws Exception { DatagramChannel ch = javaChannel(); ByteBuf buffer = alloc().directBuffer(config().getReceivePacketSize()); boolean free = true; try { ByteBuffer data = buffer.nioBuffer(buffer.writerIndex(), buffer.writableBytes()); InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(data); if (remoteAddress == null) { return 0; } buf.add( new DatagramPacket( buffer.writerIndex(buffer.writerIndex() + data.remaining()), remoteAddress)); free = false; return 1; } catch (Throwable cause) { if (cause instanceof Error) { throw (Error) cause; } if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } if (cause instanceof Exception) { throw (Exception) cause; } throw new ChannelException(cause); } finally { if (free) { buffer.free(); } } }
private static ByteBuf encodeHeaderBlock(int version, SpdyHeaderBlock headerFrame) throws Exception { Set<String> names = headerFrame.getHeaderNames(); int numHeaders = names.size(); if (numHeaders == 0) { return Unpooled.EMPTY_BUFFER; } if (numHeaders > SPDY_MAX_NV_LENGTH) { throw new IllegalArgumentException("header block contains too many headers"); } ByteBuf headerBlock = Unpooled.buffer(); writeLengthField(version, headerBlock, numHeaders); for (String name : names) { byte[] nameBytes = name.getBytes("UTF-8"); writeLengthField(version, headerBlock, nameBytes.length); headerBlock.writeBytes(nameBytes); int savedIndex = headerBlock.writerIndex(); int valueLength = 0; writeLengthField(version, headerBlock, valueLength); for (String value : headerFrame.getHeaders(name)) { byte[] valueBytes = value.getBytes("UTF-8"); headerBlock.writeBytes(valueBytes); headerBlock.writeByte(0); valueLength += valueBytes.length + 1; } valueLength--; if (valueLength > SPDY_MAX_NV_LENGTH) { throw new IllegalArgumentException("header exceeds allowable length: " + name); } setLengthField(version, headerBlock, savedIndex, valueLength); headerBlock.writerIndex(headerBlock.writerIndex() - 1); } return headerBlock; }
@Override protected int doReadMessages(List<Object> buf) throws Exception { DatagramChannel ch = javaChannel(); DatagramChannelConfig config = config(); RecvByteBufAllocator.Handle allocHandle = this.allocHandle; if (allocHandle == null) { this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); } ByteBuf data = allocHandle.allocate(config.getAllocator()); boolean free = true; try { ByteBuffer nioData = data.internalNioBuffer(data.writerIndex(), data.writableBytes()); int pos = nioData.position(); InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(nioData); if (remoteAddress == null) { return 0; } int readBytes = nioData.position() - pos; data.writerIndex(data.writerIndex() + readBytes); allocHandle.record(readBytes); buf.add(new DatagramPacket(data, localAddress(), remoteAddress)); free = false; return 1; } catch (Throwable cause) { PlatformDependent.throwException(cause); return -1; } finally { if (free) { data.release(); } } }
private SSLEngineResult unwrap( SSLEngine engine, ByteBuf in, int readerIndex, int len, ByteBuf out) throws SSLException { int nioBufferCount = in.nioBufferCount(); int writerIndex = out.writerIndex(); final SSLEngineResult result; if (engine instanceof OpenSslEngine && nioBufferCount > 1) { /** * If {@link OpenSslEngine} is in use, we can use a special {@link * OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} method that accepts multiple {@link * ByteBuffer}s without additional memory copies. */ OpenSslEngine opensslEngine = (OpenSslEngine) engine; try { singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes()); result = opensslEngine.unwrap(in.nioBuffers(readerIndex, len), singleBuffer); out.writerIndex(writerIndex + result.bytesProduced()); } finally { singleBuffer[0] = null; } } else { result = engine.unwrap( toByteBuffer(in, readerIndex, len), toByteBuffer(out, writerIndex, out.writableBytes())); } out.writerIndex(writerIndex + result.bytesProduced()); return result; }
private void write(ByteBuf buff, boolean end) { int readableBytes = buff.readableBytes(); if (readableBytes == 0 && !end) { // nothing to write to the connection just return return; } if (end) { completed = true; } if (!end && !chunked && !contentLengthSet()) { throw new IllegalStateException( "You must set the Content-Length header to be the total size of the message " + "body BEFORE sending any data if you are not using HTTP chunked encoding."); } written += buff.readableBytes(); if (conn == null) { if (pendingChunks == null) { pendingChunks = buff; } else { CompositeByteBuf pending; if (pendingChunks instanceof CompositeByteBuf) { pending = (CompositeByteBuf) pendingChunks; } else { pending = Unpooled.compositeBuffer(); pending.addComponent(pendingChunks).writerIndex(pendingChunks.writerIndex()); pendingChunks = pending; } pending.addComponent(buff).writerIndex(pending.writerIndex() + buff.writerIndex()); } connect(); } else { if (!headWritten) { writeHeadWithContent(buff, end); } else { if (end) { if (buff.isReadable()) { conn.writeToChannel(new DefaultLastHttpContent(buff, false)); } else { conn.writeToChannel(LastHttpContent.EMPTY_LAST_CONTENT); } } else { conn.writeToChannel(new DefaultHttpContent(buff)); } } if (end) { conn.reportBytesWritten(written); if (respHandler != null) { conn.endRequest(); } } } }
@Override public ByteBuf translateFrame(ByteBuf readBuffer) throws LimitExedeedException, InvalidDataException { while (readBuffer.isReadable()) { switch (status) { case STATUS_H: h = readBuffer.readByte(); status = STATUS_L; break; case STATUS_L: l = readBuffer.readByte(); final int blen = Protocol.order == ByteOrder.BIG_ENDIAN ? (0x0000ff00 & (h << 8)) | (0x000000ff & l) : (0x0000ff00 & (l << 8)) | (0x000000ff & h); if (context != null) { if (blen <= 0 || blen > maxFrameSize) { throw new LimitExedeedException("帧长度非法:" + h + "/" + l + ":" + blen); } } incompleteframe = PooledByteBufAllocator.DEFAULT.buffer(blen + 16 + 2); incompleteframe = incompleteframe.order(Protocol.order); incompleteframe.writeShort(blen); status = STATUS_C; break; case STATUS_C: int len = incompleteframe.writableBytes() - 16; len = len < readBuffer.readableBytes() ? len : readBuffer.readableBytes(); // incompleteframe.writeBytes(readBuffer, len); if (readBuffer.hasMemoryAddress()) { PlatformDependent.copyMemory( readBuffer.memoryAddress() + readBuffer.readerIndex(), incompleteframe.memoryAddress() + incompleteframe.writerIndex(), len); } else if (readBuffer.hasArray()) { PlatformDependent.copyMemory( readBuffer.array(), readBuffer.arrayOffset() + readBuffer.readerIndex(), incompleteframe.memoryAddress() + incompleteframe.writerIndex(), len); } incompleteframe.writerIndex(incompleteframe.writerIndex() + len); readBuffer.readerIndex(readBuffer.readerIndex() + len); if ((incompleteframe.writableBytes() - 16) <= 0) { status = STATUS_H; return incompleteframe; } break; } } return null; }
private void ensureWritable(int pos, int len) { int ni = pos + len; int cap = buffer.capacity(); int over = ni - cap; if (over > 0) { buffer.writerIndex(cap); buffer.ensureWritable(over); } // We have to make sure that the writerindex is always positioned on the last bit of data set in // the buffer if (ni > buffer.writerIndex()) { buffer.writerIndex(ni); } }
/** Read bytes into the given {@link ByteBuf} and return the amount. */ private int doReadBytes(ByteBuf byteBuf) throws Exception { int writerIndex = byteBuf.writerIndex(); int localReadAmount; if (byteBuf.hasMemoryAddress()) { localReadAmount = Native.readAddress(fd, byteBuf.memoryAddress(), writerIndex, byteBuf.capacity()); } else { ByteBuffer buf = byteBuf.internalNioBuffer(writerIndex, byteBuf.writableBytes()); localReadAmount = Native.read(fd, buf, buf.position(), buf.limit()); } if (localReadAmount > 0) { byteBuf.writerIndex(writerIndex + localReadAmount); } return localReadAmount; }
private static SSLEngineResult wrap(SSLEngine engine, ByteBuf in, ByteBuf out) throws SSLException { ByteBuffer in0 = in.nioBuffer(); for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.wrap(in0, out0); in.skipBytes(result.bytesConsumed()); out.writerIndex(out.writerIndex() + result.bytesProduced()); if (result.getStatus() == Status.BUFFER_OVERFLOW) { out.ensureWritableBytes(engine.getSession().getPacketBufferSize()); } else { return result; } } }
/** * Puts {@code numBits} into the buffer with the value {@code value}. * * @param numBits The number of bits to put into the buffer. * @param value The value. * @throws IllegalStateException if the builder is not in bit access mode. * @throws IllegalArgumentException if the number of bits is not between 1 and 31 inclusive. */ public void putBits(int numBits, int value) { if (numBits <= 0 || numBits > 32) { throw new IllegalArgumentException("Number of bits must be between 1 and 31 inclusive"); } checkBitAccess(); int bytePos = bitIndex >> 3; int bitOffset = 8 - (bitIndex & 7); bitIndex += numBits; int requiredSpace = bytePos - buffer.writerIndex() + 1; requiredSpace += (numBits + 7) / 8; buffer.ensureWritable(requiredSpace); for (; numBits > bitOffset; bitOffset = 8) { int tmp = buffer.getByte(bytePos); tmp &= ~BITMASKS[bitOffset]; tmp |= (value >> (numBits - bitOffset)) & BITMASKS[bitOffset]; buffer.setByte(bytePos++, tmp); numBits -= bitOffset; } if (numBits == bitOffset) { int tmp = buffer.getByte(bytePos); tmp &= ~BITMASKS[bitOffset]; tmp |= value & BITMASKS[bitOffset]; buffer.setByte(bytePos, tmp); } else { int tmp = buffer.getByte(bytePos); tmp &= ~(BITMASKS[numBits] << (bitOffset - numBits)); tmp |= (value & BITMASKS[numBits]) << (bitOffset - numBits); buffer.setByte(bytePos, tmp); } }
@Override public HttpContent readChunk(ChannelHandlerContext ctx) throws Exception { long offset = this.offset; if (offset >= endOffset) { if (sentLastChunk) { return null; } else { // Send last chunk for this file sentLastChunk = true; return new DefaultLastHttpContent(); } } int chunkSize = (int) Math.min(this.chunkSize, endOffset - offset); // Check if the buffer is backed by an byte array. If so we can optimize it a bit an safe a copy ByteBuf buf = ctx.alloc().heapBuffer(chunkSize); boolean release = true; try { file.readFully(buf.array(), buf.arrayOffset(), chunkSize); buf.writerIndex(chunkSize); this.offset = offset + chunkSize; release = false; return new DefaultHttpContent(buf); } finally { if (release) { buf.release(); } } }
public void switchToBitAccess() { if (mode == AccessMode.BIT_ACCESS) { throw new IllegalStateException("Already in bit access mode"); } mode = AccessMode.BIT_ACCESS; bitIndex = buffer.writerIndex() * 8; }
private boolean handleCompressedFrame(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (!in.isReadable(FRAME_COMPRESS_HEADER_LENGTH)) { return false; } int compressedPayloadLength = in.readInt(); if (!in.isReadable(compressedPayloadLength)) { return false; } // decompress payload Inflater inflater = new Inflater(); if (in.hasArray()) { inflater.setInput(in.array(), in.arrayOffset() + in.readerIndex(), compressedPayloadLength); in.skipBytes(compressedPayloadLength); } else { byte[] array = new byte[compressedPayloadLength]; in.readBytes(array); inflater.setInput(array); } while (!inflater.finished()) { ByteBuf decompressed = ctx.alloc().heapBuffer(1024, 1024); byte[] outArray = decompressed.array(); int count = inflater.inflate(outArray, decompressed.arrayOffset(), decompressed.writableBytes()); decompressed.writerIndex(count); // put data in the pipeline out.add(decompressed); } return true; }
public void switchToByteAccess() { if (mode == AccessMode.BYTE_ACCESS) { throw new IllegalStateException("Already in byte access mode"); } mode = AccessMode.BYTE_ACCESS; buffer.writerIndex((bitIndex + 7) / 8); }
private static SSLEngineResult unwrap(SSLEngine engine, ByteBuf in, ByteBuf out) throws SSLException { ByteBuffer in0 = in.nioBuffer(); for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.unwrap(in0, out0); in.skipBytes(result.bytesConsumed()); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: out.ensureWritableBytes(engine.getSession().getApplicationBufferSize()); break; default: return result; } } }
private void checkPrintableAscii(final ByteBuf buffer) { final ByteBuf tmpBuffer = buffer.slice(); final int lowerBound = tmpBuffer.readerIndex(); final int upperBound = tmpBuffer.writerIndex(); for (int idx = lowerBound; idx < upperBound; ++idx) { checkPrintableAscii(tmpBuffer.getByte(idx)); } }
private void writeBody(ByteBuf buffer) { byte nullVal = 0; BufferUtil.writeWithLength(buffer, catalog, nullVal); BufferUtil.writeWithLength(buffer, db, nullVal); BufferUtil.writeWithLength(buffer, table, nullVal); BufferUtil.writeWithLength(buffer, orgTable, nullVal); BufferUtil.writeWithLength(buffer, name, nullVal); BufferUtil.writeWithLength(buffer, orgName, nullVal); buffer.writeByte((byte) 0x0C); BufferUtil.writeUB2(buffer, charsetIndex); BufferUtil.writeUB4(buffer, length); buffer.writeByte((byte) (type & 0xff)); BufferUtil.writeUB2(buffer, flags); buffer.writeByte(decimals); buffer.writerIndex(buffer.writerIndex() + FILLER.length); if (definition != null) { BufferUtil.writeWithLength(buffer, definition); } }
@Override public byte[] getBodyBytes() { if (sentResponse) { body.resetReaderIndex(); byte[] bytes = new byte[body.writerIndex()]; body.readBytes(bytes, 0, bytes.length); return bytes; } else { return null; } }
@Override public void serverSend( final Receiver receiver, final Delivery delivery, String address, int messageFormat, ByteBuf messageEncoded) throws Exception { EncodedMessage encodedMessage = new EncodedMessage( messageFormat, messageEncoded.array(), messageEncoded.arrayOffset(), messageEncoded.writerIndex()); ServerMessage message = manager.getConverter().inbound(encodedMessage); // use the address on the receiver if not null, if null let's hope it was set correctly on the // message if (address != null) { message.setAddress(new SimpleString(address)); } recoverContext(); try { serverSession.send(message, false); manager .getServer() .getStorageManager() .afterCompleteOperations( new IOCallback() { @Override public void done() { synchronized (connection.getLock()) { delivery.settle(); connection.flush(); } } @Override public void onError(int errorCode, String errorMessage) { synchronized (connection.getLock()) { receiver.setCondition( new ErrorCondition( AmqpError.ILLEGAL_STATE, errorCode + ":" + errorMessage)); connection.flush(); } } }); } finally { resetContext(); } }
/** * Encode a simple UA TCP message. * * @param messageType {@link MessageType#Hello}, {@link MessageType#Acknowledge}, or {@link * MessageType#Error}. * @param messageEncoder a function that encodes the message payload. * @param buffer the {@link ByteBuf} to encode into. */ private static ByteBuf encode( MessageType messageType, Consumer<ByteBuf> messageEncoder, ByteBuf buffer) throws UaException { buffer.writeMedium(MessageType.toMediumInt(messageType)); buffer.writeByte('F'); int lengthIndex = buffer.writerIndex(); buffer.writeInt(0); int indexBefore = buffer.writerIndex(); messageEncoder.accept(buffer); int indexAfter = buffer.writerIndex(); int bytesWritten = indexAfter - indexBefore; buffer.writerIndex(lengthIndex); buffer.writeInt(8 + bytesWritten); buffer.writerIndex(indexAfter); return buffer; }
protected String formatBuffer(String message, ByteBuf buf) { int length = buf.readableBytes(); int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4; StringBuilder dump = new StringBuilder(rows * 80 + message.length() + 16); dump.append(message).append('(').append(length).append('B').append(')'); dump.append( NEWLINE + " +-------------------------------------------------+" + NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" + NEWLINE + "+--------+-------------------------------------------------+----------------+"); final int startIndex = buf.readerIndex(); final int endIndex = buf.writerIndex(); int i; for (i = startIndex; i < endIndex; i++) { int relIdx = i - startIndex; int relIdxMod16 = relIdx & 15; if (relIdxMod16 == 0) { dump.append(NEWLINE); dump.append(Long.toHexString(relIdx & 0xFFFFFFFFL | 0x100000000L)); dump.setCharAt(dump.length() - 9, '|'); dump.append('|'); } dump.append(BYTE2HEX[buf.getUnsignedByte(i)]); if (relIdxMod16 == 15) { dump.append(" |"); for (int j = i - 15; j <= i; j++) { dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]); } dump.append('|'); } } if ((i - startIndex & 15) != 0) { int remainder = length & 15; dump.append(HEXPADDING[remainder]); dump.append(" |"); for (int j = i - remainder; j < i; j++) { dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]); } dump.append(BYTEPADDING[remainder]); dump.append('|'); } dump.append( NEWLINE + "+--------+-------------------------------------------------+----------------+"); return dump.toString(); }
/** * Returns a decoded TXT (text) resource record, stored as an {@link java.util.ArrayList} of * {@code String}s. * * @param response the DNS response that contains the resource record being decoded * @param resource the resource record being decoded */ @Override public List<String> decode(DnsResponse response, DnsResource resource) { List<String> list = new ArrayList<String>(); ByteBuf data = resource.content().readerIndex(response.originalIndex()); int index = data.readerIndex(); while (index < data.writerIndex()) { int len = data.getUnsignedByte(index++); list.add(data.toString(index, len, CharsetUtil.UTF_8)); index += len; } return list; }
@Override public void write(ByteBuf bb, OFFlowModFailedErrorMsgVer10 message) { int startIndex = bb.writerIndex(); // fixed value property version = 1 bb.writeByte((byte) 0x1); // fixed value property type = 1 bb.writeByte((byte) 0x1); // length is length of variable message, will be updated at the end int lengthIndex = bb.writerIndex(); bb.writeShort(U16.t(0)); bb.writeInt(U32.t(message.xid)); // fixed value property errType = 3 bb.writeShort((short) 0x3); OFFlowModFailedCodeSerializerVer10.writeTo(bb, message.code); message.data.writeTo(bb); // update length field int length = bb.writerIndex() - startIndex; bb.setShort(lengthIndex, length); }
@Override public void rewriteServerbound(ByteBuf packet, int oldId, int newId) { super.rewriteServerbound(packet, oldId, newId); // Special cases int readerIndex = packet.readerIndex(); int packetId = DefinedPacket.readVarInt(packet); int packetIdLength = packet.readerIndex() - readerIndex; if (packetId == 0x18 /* Spectate */) { UUID uuid = DefinedPacket.readUUID(packet); ProxiedPlayer player; if ((player = BungeeCord.getInstance().getPlayer(uuid)) != null) { int previous = packet.writerIndex(); packet.readerIndex(readerIndex); packet.writerIndex(readerIndex + packetIdLength); DefinedPacket.writeUUID( ((UserConnection) player).getPendingConnection().getOfflineId(), packet); packet.writerIndex(previous); } } packet.readerIndex(readerIndex); }
@Override public void write(ByteBuf bb, OFMeterStatsReplyVer14 message) { int startIndex = bb.writerIndex(); // fixed value property version = 5 bb.writeByte((byte) 0x5); // fixed value property type = 19 bb.writeByte((byte) 0x13); // length is length of variable message, will be updated at the end int lengthIndex = bb.writerIndex(); bb.writeShort(U16.t(0)); bb.writeInt(U32.t(message.xid)); // fixed value property statsType = 9 bb.writeShort((short) 0x9); OFStatsReplyFlagsSerializerVer14.writeTo(bb, message.flags); // pad: 4 bytes bb.writeZero(4); ChannelUtils.writeList(bb, message.entries); // update length field int length = bb.writerIndex() - startIndex; bb.setShort(lengthIndex, length); }
private static SSLEngineResult unwrap(SSLEngine engine, ByteBuffer in, ByteBuf out) throws SSLException { int overflows = 0; for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.unwrap(in, out0); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: int max = engine.getSession().getApplicationBufferSize(); switch (overflows++) { case 0: out.ensureWritable(Math.min(max, in.remaining())); break; default: out.ensureWritable(max); } break; default: return result; } } }
public void encodeJsonP( Integer jsonpIndex, Queue<Packet> packets, ByteBuf out, ByteBufAllocator allocator, int limit) throws IOException { boolean jsonpMode = jsonpIndex != null; ByteBuf buf = allocateBuffer(allocator); int i = 0; while (true) { Packet packet = packets.poll(); if (packet == null || i == limit) { break; } ByteBuf packetBuf = allocateBuffer(allocator); encodePacket(packet, packetBuf, allocator, true); int packetSize = packetBuf.writerIndex(); buf.writeBytes(toChars(packetSize)); buf.writeBytes(B64_DELIMITER); buf.writeBytes(packetBuf); packetBuf.release(); i++; for (ByteBuf attachment : packet.getAttachments()) { ByteBuf encodedBuf = Base64.encode(attachment, Base64Dialect.URL_SAFE); buf.writeBytes(toChars(encodedBuf.readableBytes() + 2)); buf.writeBytes(B64_DELIMITER); buf.writeBytes(BINARY_HEADER); buf.writeBytes(encodedBuf); } } if (jsonpMode) { out.writeBytes(JSONP_HEAD); out.writeBytes(toChars(jsonpIndex)); out.writeBytes(JSONP_START); } processUtf8(buf, out, jsonpMode); buf.release(); if (jsonpMode) { out.writeBytes(JSONP_END); } }