Example #1
0
 private void readPriority(Handler handler, int streamId) throws IOException {
   int w1 = source.readInt();
   boolean exclusive = (w1 & 0x80000000) != 0;
   int streamDependency = (w1 & 0x7fffffff);
   int weight = (source.readByte() & 0xff) + 1;
   handler.priority(streamId, streamDependency, weight, exclusive);
 }
Example #2
0
 /**
  * Eagerly reads {@code byteCount} bytes from the source before launching a background task to
  * process the data. This avoids corrupting the stream.
  */
 private void pushDataLater(
     final int streamId,
     final BufferedSource source,
     final int byteCount,
     final boolean inFinished)
     throws IOException {
   final Buffer buffer = new Buffer();
   source.require(byteCount); // Eagerly read the frame before firing client thread.
   source.read(buffer, byteCount);
   if (buffer.size() != byteCount) throw new IOException(buffer.size() + " != " + byteCount);
   pushExecutor.execute(
       new NamedRunnable("OkHttp %s Push Data[%s]", hostname, streamId) {
         @Override
         public void execute() {
           try {
             boolean cancel = pushObserver.onData(streamId, buffer, byteCount, inFinished);
             if (cancel) frameWriter.rstStream(streamId, ErrorCode.CANCEL);
             if (cancel || inFinished) {
               synchronized (FramedConnection.this) {
                 currentPushRequests.remove(streamId);
               }
             }
           } catch (IOException ignored) {
           }
         }
       });
 }
Example #3
0
    private void readContinuationHeader() throws IOException {
      int previousStreamId = streamId;

      length = left = readMedium(source);
      byte type = (byte) (source.readByte() & 0xff);
      flags = (byte) (source.readByte() & 0xff);
      if (logger.isLoggable(FINE)) logger.fine(formatHeader(true, streamId, length, type, flags));
      streamId = (source.readInt() & 0x7fffffff);
      if (type != TYPE_CONTINUATION) throw ioException("%s != TYPE_CONTINUATION", type);
      if (streamId != previousStreamId) throw ioException("TYPE_CONTINUATION streamId changed");
    }
Example #4
0
 private void readPushPromise(Handler handler, int length, byte flags, int streamId)
     throws IOException {
   if (streamId == 0) {
     throw ioException("PROTOCOL_ERROR: TYPE_PUSH_PROMISE streamId == 0");
   }
   short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;
   int promisedStreamId = source.readInt() & 0x7fffffff;
   length -= 4; // account for above read.
   length = lengthWithoutPadding(length, flags, padding);
   List<Header> headerBlock = readHeaderBlock(length, padding, flags, streamId);
   handler.pushPromise(streamId, promisedStreamId, headerBlock);
 }
Example #5
0
  private void readHeader() throws IOException {
    if (closed) throw new IOException("closed");

    int b0 = source.readByte() & 0xff;

    opcode = b0 & B0_MASK_OPCODE;
    isFinalFrame = (b0 & B0_FLAG_FIN) != 0;
    isControlFrame = (b0 & OPCODE_FLAG_CONTROL) != 0;

    // Control frames must be final frames (cannot contain continuations).
    if (isControlFrame && !isFinalFrame) {
      throw new ProtocolException("Control frames must be final.");
    }

    boolean reservedFlag1 = (b0 & B0_FLAG_RSV1) != 0;
    boolean reservedFlag2 = (b0 & B0_FLAG_RSV2) != 0;
    boolean reservedFlag3 = (b0 & B0_FLAG_RSV3) != 0;
    if (reservedFlag1 || reservedFlag2 || reservedFlag3) {
      // Reserved flags are for extensions which we currently do not support.
      throw new ProtocolException("Reserved flags are unsupported.");
    }

    int b1 = source.readByte() & 0xff;

    isMasked = (b1 & B1_FLAG_MASK) != 0;
    if (isMasked == isClient) {
      // Masked payloads must be read on the server. Unmasked payloads must be read on the client.
      throw new ProtocolException("Client-sent frames must be masked. Server sent must not.");
    }

    // Get frame length, optionally reading from follow-up bytes if indicated by special values.
    frameLength = b1 & B1_MASK_LENGTH;
    if (frameLength == PAYLOAD_SHORT) {
      frameLength = source.readShort() & 0xffffL; // Value is unsigned.
    } else if (frameLength == PAYLOAD_LONG) {
      frameLength = source.readLong();
      if (frameLength < 0) {
        throw new ProtocolException(
            "Frame length 0x" + Long.toHexString(frameLength) + " > 0x7FFFFFFFFFFFFFFF");
      }
    }
    frameBytesRead = 0;

    if (isControlFrame && frameLength > PAYLOAD_BYTE_MAX) {
      throw new ProtocolException("Control frame must be less than " + PAYLOAD_BYTE_MAX + "B.");
    }

    if (isMasked) {
      // Read the masking key as bytes so that they can be used directly for unmasking.
      source.readFully(maskKey);
    }
  }
Example #6
0
 private static long readLong(BufferedSource source) throws IOException {
   try {
     long result = source.readDecimalLong();
     String line = source.readUtf8LineStrict();
     if (!line.isEmpty()) {
       throw new IOException("expected new line was \"" + line + "\"");
     }
     return result;
   } catch (NumberFormatException e) {
     e.printStackTrace();
     throw new IOException(e.getMessage());
   }
 }
Example #7
0
    private void readSettings(Handler handler, int length, byte flags, int streamId)
        throws IOException {
      if (streamId != 0) throw ioException("TYPE_SETTINGS streamId != 0");
      if ((flags & FLAG_ACK) != 0) {
        if (length != 0) throw ioException("FRAME_SIZE_ERROR ack frame should be empty!");
        handler.ackSettings();
        return;
      }

      if (length % 6 != 0) throw ioException("TYPE_SETTINGS length %% 6 != 0: %s", length);
      Settings settings = new Settings();
      for (int i = 0; i < length; i += 6) {
        short id = source.readShort();
        int value = source.readInt();

        switch (id) {
          case 1: // SETTINGS_HEADER_TABLE_SIZE
            break;
          case 2: // SETTINGS_ENABLE_PUSH
            if (value != 0 && value != 1) {
              throw ioException("PROTOCOL_ERROR SETTINGS_ENABLE_PUSH != 0 or 1");
            }
            break;
          case 3: // SETTINGS_MAX_CONCURRENT_STREAMS
            id = 4; // Renumbered in draft 10.
            break;
          case 4: // SETTINGS_INITIAL_WINDOW_SIZE
            id = 7; // Renumbered in draft 10.
            if (value < 0) {
              throw ioException("PROTOCOL_ERROR SETTINGS_INITIAL_WINDOW_SIZE > 2^31 - 1");
            }
            break;
          case 5: // SETTINGS_MAX_FRAME_SIZE
            if (value < INITIAL_MAX_FRAME_SIZE || value > 16777215) {
              throw ioException("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: %s", value);
            }
            break;
          case 6: // SETTINGS_MAX_HEADER_LIST_SIZE
            break; // Advisory only, so ignored.
          default:
            throw ioException("PROTOCOL_ERROR invalid settings id: %s", id);
        }
        settings.set(id, 0, value);
      }
      handler.settings(false, settings);
      if (settings.getHeaderTableSize() >= 0) {
        hpackReader.headerTableSizeSetting(settings.getHeaderTableSize());
      }
    }
Example #8
0
    private void readData(Handler handler, int length, byte flags, int streamId)
        throws IOException {
      // TODO: checkState open or half-closed (local) or raise STREAM_CLOSED
      boolean inFinished = (flags & FLAG_END_STREAM) != 0;
      boolean gzipped = (flags & FLAG_COMPRESSED) != 0;
      if (gzipped) {
        throw ioException("PROTOCOL_ERROR: FLAG_COMPRESSED without SETTINGS_COMPRESS_DATA");
      }

      short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;
      length = lengthWithoutPadding(length, flags, padding);

      handler.data(inFinished, streamId, source, length);
      source.skip(padding);
    }
Example #9
0
    @Override
    public long read(Buffer sink, long byteCount) throws IOException {
      while (left == 0) {
        source.skip(padding);
        padding = 0;
        if ((flags & FLAG_END_HEADERS) != 0) return -1;
        readContinuationHeader();
        // TODO: test case for empty continuation header?
      }

      long read = source.read(sink, Math.min(byteCount, left));
      if (read == -1) return -1;
      left -= read;
      return read;
    }
Example #10
0
 private void readWindowUpdate(Handler handler, int length, byte flags, int streamId)
     throws IOException {
   if (length != 4) throw ioException("TYPE_WINDOW_UPDATE length !=4: %s", length);
   long increment = (source.readInt() & 0x7fffffffL);
   if (increment == 0) throw ioException("windowSizeIncrement was 0", increment);
   handler.windowUpdate(streamId, increment);
 }
Example #11
0
  private void readControlFrame() throws IOException {
    Buffer buffer = null;
    if (frameBytesRead < frameLength) {
      buffer = new Buffer();

      if (isClient) {
        source.readFully(buffer, frameLength);
      } else {
        while (frameBytesRead < frameLength) {
          int toRead = (int) Math.min(frameLength - frameBytesRead, maskBuffer.length);
          int read = source.read(maskBuffer, 0, toRead);
          if (read == -1) throw new EOFException();
          toggleMask(maskBuffer, read, maskKey, frameBytesRead);
          buffer.write(maskBuffer, 0, read);
          frameBytesRead += read;
        }
      }
    }

    switch (opcode) {
      case OPCODE_CONTROL_PING:
        frameCallback.onPing(buffer);
        break;
      case OPCODE_CONTROL_PONG:
        frameCallback.onPong(buffer);
        break;
      case OPCODE_CONTROL_CLOSE:
        int code = 1000;
        String reason = "";
        if (buffer != null) {
          long bufferSize = buffer.size();
          if (bufferSize == 1) {
            throw new ProtocolException("Malformed close payload length of 1.");
          } else if (bufferSize != 0) {
            code = buffer.readShort();
            validateCloseCode(code, false);

            reason = buffer.readUtf8();
          }
        }
        frameCallback.onClose(code, reason);
        closed = true;
        break;
      default:
        throw new ProtocolException("Unknown control opcode: " + toHexString(opcode));
    }
  }
Example #12
0
  /**
   * Peeks up to {@code byteCount} bytes from the response body and returns them as a new response
   * body. If fewer than {@code byteCount} bytes are in the response body, the full response body is
   * returned. If more than {@code byteCount} bytes are in the response body, the returned value
   * will be truncated to {@code byteCount} bytes.
   *
   * <p>It is an error to call this method after the body has been consumed.
   *
   * <p><strong>Warning:</strong> this method loads the requested bytes into memory. Most
   * applications should set a modest limit on {@code byteCount}, such as 1 MiB.
   */
  public ResponseBody peekBody(long byteCount) throws IOException {
    BufferedSource source = body.source();
    source.request(byteCount);
    Buffer copy = source.buffer().clone();

    // There may be more than byteCount bytes in source.buffer(). If there is, return a prefix.
    Buffer result;
    if (copy.size() > byteCount) {
      result = new Buffer();
      result.write(copy, byteCount);
      copy.clear();
    } else {
      result = copy;
    }

    return ResponseBody.create(body.contentType(), result.size(), result);
  }
Example #13
0
  public static @NonNull SmashNetworkData perform(SmashRequest<?> request) throws SmashError {
    SmashNetworkData data = new SmashNetworkData();

    try {
      Request.Builder okBuilder = new Request.Builder().url(request.getUrl());
      okBuilder.removeHeader("User-Agent").addHeader("User-Agent", Smash.getUserAgent());

      BufferedSource body = getBody(request);
      switch (request.getMethod()) {
        case GET:
          okBuilder = okBuilder.get();
          break;
        case POST:
          okBuilder = okBuilder.post(convertBody(request, body));
          break;
        case PUT:
          okBuilder = okBuilder.put(convertBody(request, body));
          break;
        case DELETE:
          okBuilder = okBuilder.delete(convertBody(request, body));
          break;
        case HEAD:
          okBuilder = okBuilder.head();
          break;
        case PATCH:
          okBuilder = okBuilder.patch(convertBody(request, body));
          break;
      }

      Request okRequest = okBuilder.build();
      Response okResponse = sHttpClient.newCall(okRequest).execute();

      if (body != null) {
        body.close();
      }

      data.code = okResponse.code();
      data.headers = okResponse.headers();
      data.source = okResponse.body().source();
      data.length = okResponse.body().contentLength();
    } catch (IOException ioe) {
      throw new SmashError(ioe);
    }

    return data;
  }
Example #14
0
 private void readGoAway(Handler handler, int length, byte flags, int streamId)
     throws IOException {
   if (length < 8) throw ioException("TYPE_GOAWAY length < 8: %s", length);
   if (streamId != 0) throw ioException("TYPE_GOAWAY streamId != 0");
   int lastStreamId = source.readInt();
   int errorCodeInt = source.readInt();
   int opaqueDataLength = length - 8;
   ErrorCode errorCode = ErrorCode.fromHttp2(errorCodeInt);
   if (errorCode == null) {
     throw ioException("TYPE_GOAWAY unexpected error code: %d", errorCodeInt);
   }
   ByteString debugData = EMPTY;
   if (opaqueDataLength > 0) { // Must read debug data in order to not corrupt the connection.
     debugData = source.readByteString(opaqueDataLength);
   }
   handler.goAway(lastStreamId, errorCode, debugData);
 }
Example #15
0
 private static RequestBody convertBody(SmashRequest request, BufferedSource body)
     throws SmashError {
   try {
     return RequestBody.create(MediaType.parse(request.getBodyContentType()), body.readUtf8());
   } catch (IOException ioe) {
     throw new SmashError(ioe);
   }
 }
Example #16
0
    /**
     * Reads an entry from an input stream. A typical entry looks like this:
     *
     * <pre>{@code
     * http://google.com/foo
     * GET
     * 2
     * Accept-Language: fr-CA
     * Accept-Charset: UTF-8
     * HTTP/1.1 200 OK
     * 3
     * Content-Type: image/png
     * Content-Length: 100
     * Cache-Control: max-age=600
     * }</pre>
     *
     * <p>A typical HTTPS file looks like this:
     *
     * <pre>{@code
     * https://google.com/foo
     * GET
     * 2
     * Accept-Language: fr-CA
     * Accept-Charset: UTF-8
     * HTTP/1.1 200 OK
     * 3
     * Content-Type: image/png
     * Content-Length: 100
     * Cache-Control: max-age=600
     *
     * AES_256_WITH_MD5
     * 2
     * base64-encoded peerCertificate[0]
     * base64-encoded peerCertificate[1]
     * -1
     * }</pre>
     *
     * The file is newline separated. The first two lines are the URL and the request method. Next
     * is the number of HTTP Vary request header lines, followed by those lines.
     *
     * <p>Next is the response status line, followed by the number of HTTP response header lines,
     * followed by those lines.
     *
     * <p>HTTPS responses also contain SSL session information. This begins with a blank line, and
     * then a line containing the cipher suite. Next is the length of the peer certificate chain.
     * These certificates are base64-encoded and appear each on their own line. The next line
     * contains the length of the local certificate chain. These certificates are also
     * base64-encoded and appear each on their own line. A length of -1 is used to encode a null
     * array.
     */
    public Entry(Source in) throws IOException {
      try {
        BufferedSource source = Okio.buffer(in);
        url = source.readUtf8LineStrict();
        requestMethod = source.readUtf8LineStrict();
        if (readInt(source) == 1) {
          MediaType contentType = MediaType.parse(source.readUtf8LineStrict());
          int contentLength = readInt(source);
          requestBody = RequestBody.create(contentType, source.readByteArray(contentLength));
        } else {
          requestBody = null;
        }
        Headers.Builder varyHeadersBuilder = new Headers.Builder();
        int varyRequestHeaderLineCount = readInt(source);
        for (int i = 0; i < varyRequestHeaderLineCount; i++) {
          OkHttpAccess.addLenient(varyHeadersBuilder, source.readUtf8LineStrict());
        }
        varyHeaders = varyHeadersBuilder.build();

        StatusLine statusLine = StatusLine.parse(source.readUtf8LineStrict());
        protocol = statusLine.protocol;
        code = statusLine.code;
        message = statusLine.message;
        Headers.Builder responseHeadersBuilder = new Headers.Builder();
        int responseHeaderLineCount = readInt(source);
        for (int i = 0; i < responseHeaderLineCount; i++) {
          OkHttpAccess.addLenient(responseHeadersBuilder, source.readUtf8LineStrict());
        }
        responseHeaders = responseHeadersBuilder.build();

        if (isHttps()) {
          String blank = source.readUtf8LineStrict();
          if (blank.length() > 0) {
            throw new IOException("expected \"\" but was \"" + blank + "\"");
          }
          String cipherSuite = source.readUtf8LineStrict();
          List<Certificate> peerCertificates = readCertificateList(source);
          List<Certificate> localCertificates = readCertificateList(source);
          handshake = Handshake.get(cipherSuite, peerCertificates, localCertificates);
        } else {
          handshake = null;
        }
      } finally {
        in.close();
      }
    }
Example #17
0
 @Override
 public void readConnectionPreface() throws IOException {
   if (client) return; // Nothing to read; servers doesn't send a connection preface!
   ByteString connectionPreface = source.readByteString(CONNECTION_PREFACE.size());
   if (logger.isLoggable(FINE)) logger.fine(format("<< CONNECTION %s", connectionPreface.hex()));
   if (!CONNECTION_PREFACE.equals(connectionPreface)) {
     throw ioException("Expected a connection header but was %s", connectionPreface.utf8());
   }
 }
Example #18
0
 private void readPing(Handler handler, int length, byte flags, int streamId)
     throws IOException {
   if (length != 8) throw ioException("TYPE_PING length != 8: %s", length);
   if (streamId != 0) throw ioException("TYPE_PING streamId != 0");
   int payload1 = source.readInt();
   int payload2 = source.readInt();
   boolean ack = (flags & FLAG_ACK) != 0;
   handler.ping(ack, payload1, payload2);
 }
Example #19
0
 private void readRstStream(Handler handler, int length, byte flags, int streamId)
     throws IOException {
   if (length != 4) throw ioException("TYPE_RST_STREAM length: %d != 4", length);
   if (streamId == 0) throw ioException("TYPE_RST_STREAM streamId == 0");
   int errorCodeInt = source.readInt();
   ErrorCode errorCode = ErrorCode.fromHttp2(errorCodeInt);
   if (errorCode == null) {
     throw ioException("TYPE_RST_STREAM unexpected error code: %d", errorCodeInt);
   }
   handler.rstStream(streamId, errorCode);
 }
Example #20
0
 private Response response(DiskLruCache.Snapshot snapshot) throws IOException {
   String contentType = responseHeaders.get("Content-Type");
   Request cacheRequest =
       new Request.Builder()
           .url(url)
           .method(requestMethod, requestBody)
           .headers(varyHeaders)
           .build();
   BufferedSource source = Okio.buffer(snapshot.getSource(RESPONSE_BODY));
   byte[] bodyContent = source.readByteArray();
   MediaType mediaType = contentType == null ? null : MediaType.parse(contentType);
   return new Response.Builder()
       .request(cacheRequest)
       .protocol(protocol)
       .code(code)
       .message(message)
       .headers(responseHeaders)
       .body(new OkHttpUtil.ReusableResponseBody(mediaType, bodyContent))
       .handshake(handshake)
       .build();
 }
Example #21
0
 /** Stops the SSE stream. */
 public void stop() {
   mClosed = true;
   try {
     if (in != null) in.close();
   } catch (final IOException ignore) {
   }
   try {
     out.close();
   } catch (final IOException ignore) {
   }
   // try { if (socket != null) socket.close(); } catch (final IOException ignore) {}
 }
Example #22
0
    private List<Certificate> readCertificateList(BufferedSource source) throws IOException {
      int length = readInt(source);
      if (length == -1) return Collections.emptyList(); // OkHttp v1.2 used -1 to indicate null.

      try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        List<Certificate> result = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
          String line = source.readUtf8LineStrict();
          Buffer bytes = new Buffer();
          bytes.write(ByteString.decodeBase64(line));
          result.add(certificateFactory.generateCertificate(bytes.inputStream()));
        }
        return result;
      } catch (CertificateException e) {
        throw new IOException(e.getMessage());
      }
    }
Example #23
0
 @Override
 public void data(boolean inFinished, int streamId, BufferedSource source, int length)
     throws IOException {
   if (pushedStream(streamId)) {
     pushDataLater(streamId, source, length, inFinished);
     return;
   }
   FramedStream dataStream = getStream(streamId);
   if (dataStream == null) {
     writeSynResetLater(streamId, ErrorCode.INVALID_STREAM);
     source.skip(length);
     return;
   }
   dataStream.receiveData(source, length);
   if (inFinished) {
     dataStream.receiveFin();
   }
 }
Example #24
0
    private void readHeaders(Handler handler, int length, byte flags, int streamId)
        throws IOException {
      if (streamId == 0) throw ioException("PROTOCOL_ERROR: TYPE_HEADERS streamId == 0");

      boolean endStream = (flags & FLAG_END_STREAM) != 0;

      short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;

      if ((flags & FLAG_PRIORITY) != 0) {
        readPriority(handler, streamId);
        length -= 5; // account for above read.
      }

      length = lengthWithoutPadding(length, flags, padding);

      List<Header> headerBlock = readHeaderBlock(length, padding, flags, streamId);

      handler.headers(false, endStream, streamId, -1, headerBlock, HeadersMode.HTTP_20_HEADERS);
    }
Example #25
0
  @Override
  public Response intercept(Chain chain) throws IOException {
    Level level = this.level;

    Request request = chain.request();
    if (level == Level.NONE) {
      return chain.proceed(request);
    }

    boolean logBody = level == Level.BODY;
    boolean logHeaders = logBody || level == Level.HEADERS;

    RequestBody requestBody = request.body();
    boolean hasRequestBody = requestBody != null;

    Connection connection = chain.connection();
    Protocol protocol = connection != null ? connection.getProtocol() : Protocol.HTTP_1_1;
    String requestStartMessage =
        "--> " + request.method() + ' ' + requestPath(request.httpUrl()) + ' ' + protocol(protocol);
    if (!logHeaders && hasRequestBody) {
      requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
    }
    logger.log(requestStartMessage);

    if (logHeaders) {
      Headers headers = request.headers();
      for (int i = 0, count = headers.size(); i < count; i++) {
        logger.log(headers.name(i) + ": " + headers.value(i));
      }

      String endMessage = "--> END " + request.method();
      if (logBody && hasRequestBody) {
        Buffer buffer = new Buffer();
        requestBody.writeTo(buffer);

        Charset charset = UTF8;
        MediaType contentType = requestBody.contentType();
        if (contentType != null) {
          contentType.charset(UTF8);
        }

        logger.log("");
        logger.log(buffer.readString(charset));

        endMessage += " (" + requestBody.contentLength() + "-byte body)";
      }
      logger.log(endMessage);
    }

    long startNs = System.nanoTime();
    Response response = chain.proceed(request);
    long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);

    ResponseBody responseBody = response.body();
    logger.log(
        "<-- "
            + protocol(response.protocol())
            + ' '
            + response.code()
            + ' '
            + response.message()
            + " ("
            + tookMs
            + "ms"
            + (!logHeaders ? ", " + responseBody.contentLength() + "-byte body" : "")
            + ')');

    if (logHeaders) {
      Headers headers = response.headers();
      for (int i = 0, count = headers.size(); i < count; i++) {
        logger.log(headers.name(i) + ": " + headers.value(i));
      }

      String endMessage = "<-- END HTTP";
      if (logBody) {
        BufferedSource source = responseBody.source();
        source.request(Long.MAX_VALUE); // Buffer the entire body.
        Buffer buffer = source.buffer();

        Charset charset = UTF8;
        MediaType contentType = responseBody.contentType();
        if (contentType != null) {
          charset = contentType.charset(UTF8);
        }

        if (responseBody.contentLength() != 0) {
          logger.log("");
          logger.log(buffer.clone().readString(charset));
        }

        endMessage += " (" + buffer.size() + "-byte body)";
      }
      logger.log(endMessage);
    }

    return response;
  }
Example #26
0
 @Override
 public void close() throws IOException {
   source.close();
 }
Example #27
0
 @Override
 public boolean onData(int streamId, BufferedSource source, int byteCount, boolean last)
     throws IOException {
   source.skip(byteCount);
   return false;
 }
Example #28
0
 private void assertResponseBody(HttpURLConnection connection, String expected) throws Exception {
   BufferedSource source = buffer(source(connection.getInputStream()));
   String actual = source.readString(US_ASCII);
   source.close();
   assertEquals(expected, actual);
 }
Example #29
0
 @Override
 public Timeout timeout() {
   return source.timeout();
 }
Example #30
0
 private static int readMedium(BufferedSource source) throws IOException {
   return (source.readByte() & 0xff) << 16
       | (source.readByte() & 0xff) << 8
       | (source.readByte() & 0xff);
 }