void writeInt(int value, int prefixMask, int bits) { // Write the raw value for a single byte value. if (value < prefixMask) { out.writeByte(bits | value); return; } // Write the mask to start a multibyte value. out.writeByte(bits | prefixMask); value -= prefixMask; // Write 7 bits at a time 'til we're done. while (value >= 0x80) { int b = value & 0x7f; out.writeByte(b | 0x80); value >>>= 7; } out.writeByte(value); }
static void percentDecode(Buffer out, String encoded, int pos, int limit, boolean plusIsSpace) { int codePoint; for (int i = pos; i < limit; i += Character.charCount(codePoint)) { codePoint = encoded.codePointAt(i); if (codePoint == '%' && i + 2 < limit) { int d1 = decodeHexDigit(encoded.charAt(i + 1)); int d2 = decodeHexDigit(encoded.charAt(i + 2)); if (d1 != -1 && d2 != -1) { out.writeByte((d1 << 4) + d2); i += 2; continue; } } else if (codePoint == '+' && plusIsSpace) { out.writeByte(' '); continue; } out.writeUtf8CodePoint(codePoint); } }
/** * Returns the concatenation of 8-bit, length prefixed protocol names. * http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4 */ static byte[] concatLengthPrefixed(List<Protocol> protocols) { Buffer result = new Buffer(); for (int i = 0, size = protocols.size(); i < size; i++) { Protocol protocol = protocols.get(i); if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN. result.writeByte(protocol.toString().length()); result.writeUtf8(protocol.toString()); } return result.readByteArray(); }
private static void canonicalizeForPath(Buffer out, String input, int pos, int limit, boolean alreadyEncoded) { Buffer utf8Buffer = null; // Lazily allocated. int codePoint; for (int i = pos; i < limit; i += Character.charCount(codePoint)) { codePoint = input.codePointAt(i); if (alreadyEncoded && (codePoint == '\t' || codePoint == '\n' || codePoint == '\f' || codePoint == '\r')) { // Skip this character. } else if (codePoint < 0x20 || codePoint >= 0x7f || PATH_SEGMENT_ALWAYS_ENCODE_SET.indexOf(codePoint) != -1 || (!alreadyEncoded && (codePoint == '/' || codePoint == '%'))) { // Percent encode this character. if (utf8Buffer == null) { utf8Buffer = new Buffer(); } utf8Buffer.writeUtf8CodePoint(codePoint); while (!utf8Buffer.exhausted()) { int b = utf8Buffer.readByte() & 0xff; out.writeByte('%'); out.writeByte(HEX_DIGITS[(b >> 4) & 0xf]); out.writeByte(HEX_DIGITS[b & 0xf]); } } else { // This character doesn't need encoding. Just copy it over. out.writeUtf8CodePoint(codePoint); } } }
/** * Either writes this request to {@code sink} or measures its content length. We have one method * do double-duty to make sure the counting and content are consistent, particularly when it comes * to awkward operations like measuring the encoded length of header strings, or the * length-in-digits of an encoded integer. */ private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) { long byteCount = 0L; Buffer buffer; if (countBytes) { buffer = new Buffer(); } else { buffer = sink.buffer(); } for (int i = 0, size = encodedNames.size(); i < size; i++) { if (i > 0) buffer.writeByte('&'); buffer.writeUtf8(encodedNames.get(i)); buffer.writeByte('='); buffer.writeUtf8(encodedValues.get(i)); } if (countBytes) { byteCount = buffer.size(); buffer.clear(); } return byteCount; }
private void parseData(Buffer data, long end) throws IOException { data.writeByte('\n'); end -= skipNameAndDivider(4L); source.readFully(data, end); skipCrAndOrLf(); }
static void percentDecode(Buffer out, String encoded, int pos, int limit) { int codePoint; for (int i = pos; i < limit; i += Character.charCount(codePoint)) { codePoint = encoded.codePointAt(i); if (codePoint == '%' && i + 2 < limit) { int d1 = decodeHexDigit(encoded.charAt(i + 1)); int d2 = decodeHexDigit(encoded.charAt(i + 2)); if (d1 != -1 && d2 != -1) { out.writeByte((d1 << 4) + d2); i += 2; continue; } } out.writeUtf8CodePoint(codePoint); } }
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(); }
/** * Returns the concatenation of 8-bit, length prefixed protocol names. * http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4 */ static byte[] concatLengthPrefixed(List<Protocol> protocols) { Buffer result = new Buffer(); for (int i = 0, size = protocols.size(); i < size; i++) { Protocol protocol = protocols.get(i); if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN. result.writeByte(protocol.toString().length()); result.writeUtf8(protocol.toString()); } return result.readByteArray(); }
public static ByteString encodeQuery(String host, int type) { Buffer buf = new Buffer(); buf.writeShort(0); // query id buf.writeShort(256); // flags with recursion buf.writeShort(1); // question count buf.writeShort(0); // answerCount buf.writeShort(0); // authorityResourceCount buf.writeShort(0); // additional Buffer nameBuf = new Buffer(); final String[] labels = host.split("\\."); for (String label : labels) { long utf8ByteCount = Utf8.size(label); if (utf8ByteCount != label.length()) { throw new IllegalArgumentException("non-ascii hostname: " + host); } nameBuf.writeByte((byte) utf8ByteCount); nameBuf.writeUtf8(label); } nameBuf.writeByte(0); // end nameBuf.copyTo(buf, 0, nameBuf.size()); buf.writeShort(type); buf.writeShort(1); // CLASS_IN return buf.readByteString(); }
} else if (headerNameIndex == -1) { out.writeByte(0x40); writeByteString(name); writeByteString(value);
@Test public void readMissingContinuationBytesThrowsEofException() throws Exception { Buffer buffer = new Buffer(); buffer.writeByte(0xdf); try { buffer.readUtf8CodePoint(); fail(); } catch (EOFException expected) { } assertFalse(buffer.exhausted()); // Prefix byte wasn't consumed. }
@Test public void readLeadingContinuationByteReturnsReplacementCharacter() throws Exception { Buffer buffer = new Buffer(); buffer.writeByte(0xbf); assertEquals(REPLACEMENT_CODE_POINT, buffer.readUtf8CodePoint()); assertTrue(buffer.exhausted()); }
/** * For portability, it is a good idea to export the gzipped bytes and try running gzip. Ex. * {@code echo gzipped | base64 --decode | gzip -l -v} */ @Test public void gunzip_withAll() throws Exception { Buffer gzipped = new Buffer(); gzipped.write(gzipHeaderWithFlags((byte) 0x1c)); gzipped.writeShort(TestUtil.reverseBytes((short) 7)); // little endian extra length gzipped.write("blubber".getBytes(UTF_8), 0, 7); gzipped.write("foo.txt".getBytes(UTF_8), 0, 7); gzipped.writeByte(0); // zero-terminated gzipped.write("rubbish".getBytes(UTF_8), 0, 7); gzipped.writeByte(0); // zero-terminated gzipped.write(deflated); gzipped.write(gzipTrailer); assertGzipped(gzipped); }
@Test public void gunzip_withName() throws Exception { Buffer gzipped = new Buffer(); gzipped.write(gzipHeaderWithFlags((byte) 0x08)); gzipped.write("foo.txt".getBytes(UTF_8), 0, 7); gzipped.writeByte(0); // zero-terminated gzipped.write(deflated); gzipped.write(gzipTrailer); assertGzipped(gzipped); }
@Test public void gunzip_withComment() throws Exception { Buffer gzipped = new Buffer(); gzipped.write(gzipHeaderWithFlags((byte) 0x10)); gzipped.write("rubbish".getBytes(UTF_8), 0, 7); gzipped.writeByte(0); // zero-terminated gzipped.write(deflated); gzipped.write(gzipTrailer); assertGzipped(gzipped); }
@Test public void gunzipThrowsIfSourceIsNotExhausted() throws Exception { Buffer gzippedSource = new Buffer() .write(ByteString.decodeHex("1f8b08000000000000004b4c4a0600c241243503000000")); // 'abc' gzippedSource.writeByte('d'); // This byte shouldn't be here! BufferedSource gunzippedSource = Okio.buffer(new GzipSource(gzippedSource)); assertEquals('a', gunzippedSource.readByte()); assertEquals('b', gunzippedSource.readByte()); assertEquals('c', gunzippedSource.readByte()); try { gunzippedSource.readByte(); fail(); } catch (IOException expected) { } }