/**
  * 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) {
           }
         }
       });
 }
Beispiel #2
0
 @Override
 void writeBody(final BufferedSource in, final BufferedSink out) throws IOException {
   try {
     final ResponseBody data = body();
     if (data != null) {
       final long length = data.contentLength();
       if (length > 0) {
         out.write(data.source(), data.contentLength());
         out.flush();
       } else if (length < 0) {
         final Buffer buffer = new Buffer();
         final long step = 65536;
         long read;
         while ((read = data.source().read(buffer, step)) > -1) {
           buffer.flush();
           out.write(buffer, read);
           out.flush();
         }
       }
     }
   } finally {
     //        try { in.close(); } catch (final IOException ignore) {}
     //        try { out.close(); } catch (final IOException ignore) {}
     //        try { socket.close(); } catch (final IOException ignore) {}
   }
 }
  public static void serializeAndCommitResponse(Response response, DiskLruCache.Editor edit)
      throws IOException {
    if (edit == null) {
      return;
    }

    boolean successful = false;
    try {
      new Entry(response).writeTo(edit);
      Buffer buffer = new Buffer();
      ResponseBody body = response.body();
      if (body != null) {
        body.source().read(buffer, body.contentLength());
      }
      Sink sink = edit.newSink(RESPONSE_BODY);
      sink.write(buffer, buffer.size());
      sink.close();
      successful = true;
    } finally {
      if (successful) {
        commitQuitely(edit);
      } else {
        abortQuietly(edit);
      }
    }
  }
Beispiel #4
0
 /**
  * Sets a response body built from the specified text.
  *
  * @param text the string value.
  * @param contentType the media type.
  * @return this
  */
 public Builder body(final String text, final MediaType contentType) {
   if (text == null) return body((ResponseBody) null);
   final Buffer buffer = new Buffer().writeUtf8(text);
   this.mBody = new BufferResponse(contentType, buffer);
   contentLength(buffer.size());
   contentType(contentType);
   return this;
 }
  @Override
  public synchronized void onResponse(Response response) throws IOException {
    Buffer buffer = new Buffer();
    Response.Body body = response.body();
    body.source().readAll(buffer);

    responses.add(new RecordedResponse(response.request(), response, buffer.readUtf8(), null));
    notifyAll();
  }
 @Override
 public InputStream getMessagePayload() throws IOException {
   if (request.body() == null) {
     return null;
   }
   Buffer buf = new Buffer();
   request.body().writeTo(buf);
   return buf.inputStream();
 }
Beispiel #7
0
 private static String bodyAsString(RequestBody body) {
   try {
     Buffer buffer = new Buffer();
     body.writeTo(buffer);
     return buffer.readString(body.contentType().charset());
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
Beispiel #8
0
 /**
  * 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 NPN.
     result.writeByte(protocol.toString().length());
     result.writeUtf8(protocol.toString());
   }
   return result.readByteArray();
 }
  private static String bodyToString(final Request request) {

    try {
      final Request copy = request.newBuilder().build();
      final Buffer buffer = new Buffer();
      copy.body().writeTo(buffer);
      return buffer.readUtf8();
    } catch (final IOException e) {
      return "did not work";
    }
  }
 @Override
 public RequestBody toBody(T value) {
   Buffer buffer = new Buffer();
   Writer writer = new OutputStreamWriter(buffer.outputStream(), Util.UTF_8);
   try {
     typeAdapter.toJson(writer, value);
     writer.flush();
   } catch (IOException e) {
     throw new AssertionError(e); // Writing to Buffer does no I/O.
   }
   return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
 }
 @Override
 public RequestBody convert(T value) throws IOException {
   Buffer buffer = new Buffer();
   Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
   try {
     gson.toJson(value, type, writer);
     writer.flush();
   } catch (IOException e) {
     throw new AssertionError(e); // Writing to Buffer does no I/O.
   }
   return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
 }
Beispiel #12
0
    void headers(boolean outFinished, int streamId, List<Header> headerBlock) throws IOException {
      if (closed) throw new IOException("closed");
      if (hpackBuffer.size() != 0) throw new IllegalStateException();
      hpackWriter.writeHeaders(headerBlock);

      long byteCount = hpackBuffer.size();
      int length = (int) Math.min(maxFrameSize, byteCount);
      byte type = TYPE_HEADERS;
      byte flags = byteCount == length ? FLAG_END_HEADERS : 0;
      if (outFinished) flags |= FLAG_END_STREAM;
      frameHeader(streamId, length, type, flags);
      sink.write(hpackBuffer, length);

      if (byteCount > length) writeContinuationFrames(streamId, byteCount - length);
    }
Beispiel #13
0
  @Override
  public Source source(File file) throws FileNotFoundException {
    Buffer result = files.get(file);
    if (result == null) throw new FileNotFoundException();

    final Source source = result.clone();
    openSources.put(source, file);

    return new ForwardingSource(source) {
      @Override
      public void close() throws IOException {
        openSources.remove(source);
        super.close();
      }
    };
  }
Beispiel #14
0
    @Override
    public long read(Buffer sink, long byteCount) throws IOException {
      if (closed) throw new IOException("closed");
      if (messageClosed) throw new IllegalStateException("closed");

      if (frameBytesRead == frameLength) {
        if (isFinalFrame) return -1; // We are exhausted and have no continuations.

        readUntilNonControlFrame();
        if (opcode != OPCODE_CONTINUATION) {
          throw new ProtocolException("Expected continuation opcode. Got: " + toHexString(opcode));
        }
        if (isFinalFrame && frameLength == 0) {
          return -1; // Fast-path for empty final frame.
        }
      }

      long toRead = Math.min(byteCount, frameLength - frameBytesRead);

      long read;
      if (isMasked) {
        toRead = Math.min(toRead, maskBuffer.length);
        read = source.read(maskBuffer, 0, (int) toRead);
        if (read == -1) throw new EOFException();
        toggleMask(maskBuffer, read, maskKey, frameBytesRead);
        sink.write(maskBuffer, 0, (int) read);
      } else {
        read = source.read(sink, toRead);
        if (read == -1) throw new EOFException();
      }

      frameBytesRead += read;
      return read;
    }
 private void logRequest(Request request, Response response, String body) throws IOException {
   if (Config.LOGS_ENABLED) {
     String requestString = request.method() + " " + request.urlString();
     if (!request.method().toLowerCase().equals("get")) {
       Buffer buffer = new Buffer();
       request.body().writeTo(buffer);
       requestString += " " + buffer.readUtf8();
     }
     if (response.code() >= 400) {
       LogHelper.d(TAG, "request failed " + requestString);
     } else {
       LogHelper.d(TAG, "request success " + requestString);
     }
     LogHelper.i(TAG, "response = " + response.code() + "  " + body);
   }
 }
Beispiel #16
0
  @Test
  public void readSendsWindowUpdateHttp2() throws Exception {
    peer.setVariantAndClient(HTTP_2, false);

    int windowSize = 100;
    int windowUpdateThreshold = 50;

    // Write the mocking script.
    peer.acceptFrame(); // SYN_STREAM
    peer.sendFrame().synReply(false, 3, headerEntries("a", "android"));
    for (int i = 0; i < 3; i++) {
      // Send frames of summing to size 50, which is windowUpdateThreshold.
      peer.sendFrame().data(false, 3, data(24), 24);
      peer.sendFrame().data(false, 3, data(25), 25);
      peer.sendFrame().data(false, 3, data(1), 1);
      peer.acceptFrame(); // connection WINDOW UPDATE
      peer.acceptFrame(); // stream WINDOW UPDATE
    }
    peer.sendFrame().data(true, 3, data(0), 0);
    peer.play();

    // Play it back.
    FramedConnection connection = connection(peer, HTTP_2);
    connection.okHttpSettings.set(INITIAL_WINDOW_SIZE, 0, windowSize);
    FramedStream stream = connection.newStream(headerEntries("b", "banana"), false, true);
    assertEquals(0, stream.unacknowledgedBytesRead);
    assertEquals(headerEntries("a", "android"), stream.getResponseHeaders());
    Source in = stream.getSource();
    Buffer buffer = new Buffer();
    buffer.writeAll(in);
    assertEquals(-1, in.read(buffer, 1));
    assertEquals(150, buffer.size());

    MockSpdyPeer.InFrame synStream = peer.takeFrame();
    assertEquals(TYPE_HEADERS, synStream.type);
    for (int i = 0; i < 3; i++) {
      List<Integer> windowUpdateStreamIds = new ArrayList<>(2);
      for (int j = 0; j < 2; j++) {
        MockSpdyPeer.InFrame windowUpdate = peer.takeFrame();
        assertEquals(TYPE_WINDOW_UPDATE, windowUpdate.type);
        windowUpdateStreamIds.add(windowUpdate.streamId);
        assertEquals(windowUpdateThreshold, windowUpdate.windowSizeIncrement);
      }
      assertTrue(windowUpdateStreamIds.contains(0)); // connection
      assertTrue(windowUpdateStreamIds.contains(3)); // stream
    }
  }
Beispiel #17
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));
    }
  }
Beispiel #18
0
    @Override
    public synchronized void pushPromise(
        int streamId, int promisedStreamId, List<Header> requestHeaders) throws IOException {
      if (closed) throw new IOException("closed");
      if (hpackBuffer.size() != 0) throw new IllegalStateException();
      hpackWriter.writeHeaders(requestHeaders);

      long byteCount = hpackBuffer.size();
      int length = (int) Math.min(maxFrameSize - 4, byteCount);
      byte type = TYPE_PUSH_PROMISE;
      byte flags = byteCount == length ? FLAG_END_HEADERS : 0;
      frameHeader(streamId, length + 4, type, flags);
      sink.writeInt(promisedStreamId & 0x7fffffff);
      sink.write(hpackBuffer, length);

      if (byteCount > length) writeContinuationFrames(streamId, byteCount - length);
    }
    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());
      }
    }
Beispiel #20
0
 /**
  * Reads until {@code in} is exhausted or the deadline has been reached. This is careful to not
  * extend the deadline if one exists already.
  */
 public static boolean skipAll(Source source, int duration, TimeUnit timeUnit) throws IOException {
   long now = System.nanoTime();
   long originalDuration =
       source.timeout().hasDeadline() ? source.timeout().deadlineNanoTime() - now : Long.MAX_VALUE;
   source.timeout().deadlineNanoTime(now + Math.min(originalDuration, timeUnit.toNanos(duration)));
   try {
     Buffer skipBuffer = new Buffer();
     while (source.read(skipBuffer, 2048) != -1) {
       skipBuffer.clear();
     }
     return true; // Success! The source has been exhausted.
   } catch (InterruptedIOException e) {
     return false; // We ran out of time before exhausting the source.
   } finally {
     if (originalDuration == Long.MAX_VALUE) {
       source.timeout().clearDeadline();
     } else {
       source.timeout().deadlineNanoTime(now + originalDuration);
     }
   }
 }
Beispiel #21
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);
  }
Beispiel #22
0
 @Override
 public long contentLength() {
   return buffer.size();
 }
 @Override
 public BufferedSource newSource(Path pathRelativeToProjectRoot) throws IOException {
   Buffer buffer = new Buffer();
   buffer.write(fileContents.get(normalizePathToProjectRoot(pathRelativeToProjectRoot)));
   return buffer;
 }
Beispiel #24
0
 @Override
 public long size(File file) {
   Buffer buffer = files.get(file);
   return buffer != null ? buffer.size() : 0L;
 }
Beispiel #25
0
 public static Buffer fileToBytes(File file) throws IOException {
   Buffer result = new Buffer();
   result.writeAll(Okio.source(file));
   return result;
 }
 private static AbstractCharSequenceAssert<?, String> assertBody(RequestBody body)
     throws IOException {
   Buffer buffer = new Buffer();
   body.writeTo(buffer);
   return assertThat(buffer.readByteString().base64());
 }
  @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;
  }
Beispiel #28
0
 static byte[] toBytes(long v) {
   okio.Buffer buffer = new okio.Buffer();
   buffer.writeLong(v);
   return buffer.readByteArray();
 }