@Override public void write(Buffer source, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (source.size() < byteCount) { throw new IllegalArgumentException("size=" + source.size() + " byteCount=" + byteCount); } if (byteCount == 0) return; source.readUnsafe(cursor); try { long remaining = byteCount; for (int length = cursor.seek(0); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } super.write(source, byteCount); }
/** * Reads a message body into across one or more frames. Control frames that occur between * fragments will be processed. If the message payload is masked this will unmask as it's being * processed. */ private void readMessage() throws IOException { while (true) { if (closed) throw new IOException("closed"); if (frameLength > 0) { source.readFully(messageFrameBuffer, frameLength); if (!isClient) { messageFrameBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(messageFrameBuffer.size() - frameLength); toggleMask(maskCursor, maskKey); maskCursor.close(); } } if (isFinalFrame) break; // We are exhausted and have no continuations. readUntilNonControlFrame(); if (opcode != OPCODE_CONTINUATION) { throw new ProtocolException("Expected continuation opcode. Got: " + toHexString(opcode)); } } } }
private void writeControlFrame(int opcode, ByteString payload) throws IOException { if (writerClosed) throw new IOException("closed"); int length = payload.size(); if (length > PAYLOAD_BYTE_MAX) { throw new IllegalArgumentException( "Payload size must be less than or equal to " + PAYLOAD_BYTE_MAX); } int b0 = B0_FLAG_FIN | opcode; sinkBuffer.writeByte(b0); int b1 = length; if (isClient) { b1 |= B1_FLAG_MASK; sinkBuffer.writeByte(b1); random.nextBytes(maskKey); sinkBuffer.write(maskKey); if (length > 0) { long payloadStart = sinkBuffer.size(); sinkBuffer.write(payload); sinkBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(payloadStart); toggleMask(maskCursor, maskKey); maskCursor.close(); } } else { sinkBuffer.writeByte(b1); sinkBuffer.write(payload); } sink.flush(); }
maskCursor.seek(bufferStart); toggleMask(maskCursor, maskKey); maskCursor.close();
maskCursor.seek(0); toggleMask(maskCursor, maskKey); maskCursor.close();
private void writeControlFrame(int opcode, ByteString payload) throws IOException { if (writerClosed) throw new IOException("closed"); int length = payload.size(); if (length > PAYLOAD_BYTE_MAX) { throw new IllegalArgumentException( "Payload size must be less than or equal to " + PAYLOAD_BYTE_MAX); } int b0 = B0_FLAG_FIN | opcode; sinkBuffer.writeByte(b0); int b1 = length; if (isClient) { b1 |= B1_FLAG_MASK; sinkBuffer.writeByte(b1); random.nextBytes(maskKey); sinkBuffer.write(maskKey); if (length > 0) { long payloadStart = sinkBuffer.size(); sinkBuffer.write(payload); sinkBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(payloadStart); toggleMask(maskCursor, maskKey); maskCursor.close(); } } else { sinkBuffer.writeByte(b1); sinkBuffer.write(payload); } sink.flush(); }
/** * Reads a message body into across one or more frames. Control frames that occur between * fragments will be processed. If the message payload is masked this will unmask as it's being * processed. */ private void readMessage() throws IOException { while (true) { if (closed) throw new IOException("closed"); if (frameLength > 0) { source.readFully(messageFrameBuffer, frameLength); if (!isClient) { messageFrameBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(messageFrameBuffer.size() - frameLength); toggleMask(maskCursor, maskKey); maskCursor.close(); } } if (isFinalFrame) break; // We are exhausted and have no continuations. readUntilNonControlFrame(); if (opcode != OPCODE_CONTINUATION) { throw new ProtocolException("Expected continuation opcode. Got: " + toHexString(opcode)); } } } }
maskCursor.seek(bufferStart); toggleMask(maskCursor, maskKey); maskCursor.close();
maskCursor.seek(0); toggleMask(maskCursor, maskKey); maskCursor.close();
private void writeControlFrame(int opcode, ByteString payload) throws IOException { if (writerClosed) throw new IOException("closed"); int length = payload.size(); if (length > PAYLOAD_BYTE_MAX) { throw new IllegalArgumentException( "Payload size must be less than or equal to " + PAYLOAD_BYTE_MAX); } int b0 = B0_FLAG_FIN | opcode; sinkBuffer.writeByte(b0); int b1 = length; if (isClient) { b1 |= B1_FLAG_MASK; sinkBuffer.writeByte(b1); random.nextBytes(maskKey); sinkBuffer.write(maskKey); if (length > 0) { long payloadStart = sinkBuffer.size(); sinkBuffer.write(payload); sinkBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(payloadStart); toggleMask(maskCursor, maskKey); maskCursor.close(); } } else { sinkBuffer.writeByte(b1); sinkBuffer.write(payload); } sink.flush(); }
/** * Reads a message body into across one or more frames. Control frames that occur between * fragments will be processed. If the message payload is masked this will unmask as it's being * processed. */ private void readMessage() throws IOException { while (true) { if (closed) throw new IOException("closed"); if (frameLength > 0) { source.readFully(messageFrameBuffer, frameLength); if (!isClient) { messageFrameBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(messageFrameBuffer.size() - frameLength); toggleMask(maskCursor, maskKey); maskCursor.close(); } } if (isFinalFrame) break; // We are exhausted and have no continuations. readUntilNonControlFrame(); if (opcode != OPCODE_CONTINUATION) { throw new ProtocolException("Expected continuation opcode. Got: " + toHexString(opcode)); } } } }
@Override public long read(Buffer sink, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (byteCount == 0) return 0; long result = super.read(sink, byteCount); if (result == -1L) return result; sink.readUnsafe(cursor); try { long remaining = result; for (int length = cursor.seek(sink.size() - result); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } return result; }
@Test public void segmentBySegmentNavigation() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = buffer.readUnsafe(); assertEquals(-1, cursor.offset); try { long lastOffset = cursor.offset; while (cursor.next() != -1L) { assertTrue(cursor.offset > lastOffset); lastOffset = cursor.offset; } assertEquals(buffer.size(), cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); } finally { cursor.close(); } }
@Test public void acquireAndRelease() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = new UnsafeCursor(); // Nothing initialized before acquire. assertEquals(-1, cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); buffer.readUnsafe(cursor); cursor.close(); // Nothing initialized after close. assertEquals(-1, cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); }
maskCursor.seek(bufferStart); toggleMask(maskCursor, maskKey); maskCursor.close();
maskCursor.seek(0); toggleMask(maskCursor, maskKey); maskCursor.close();
@Test public void releaseWithoutAcquire() throws Exception { UnsafeCursor cursor = new UnsafeCursor(); try { cursor.close(); fail(); } catch (IllegalStateException expected) { } }