Example #1
0
  @Test
  public void peerHttp2ClientDisablesPush() throws Exception {
    boolean client = false; // Peer is client, so we are server.
    Settings settings = new Settings();
    settings.set(ENABLE_PUSH, 0, 0); // The peer client disables push.

    FramedConnection connection = sendHttp2SettingsAndCheckForAck(client, settings);

    // verify the peer's settings were read and applied.
    assertFalse(connection.peerSettings.getEnablePush(true));
  }
Example #2
0
  @Test
  public void peerIncreasesMaxFrameSize() throws Exception {
    int newMaxFrameSize = 0x4001;
    Settings settings = new Settings();
    settings.set(MAX_FRAME_SIZE, 0, newMaxFrameSize);

    FramedConnection connection = sendHttp2SettingsAndCheckForAck(true, settings);

    // verify the peer's settings were read and applied.
    assertEquals(newMaxFrameSize, connection.peerSettings.getMaxFrameSize(-1));
    assertEquals(newMaxFrameSize, connection.frameWriter.maxDataLength());
  }
Example #3
0
  @Test
  public void peerHttp2ServerZerosCompressionTable() throws Exception {
    boolean client = false; // Peer is server, so we are client.
    Settings settings = new Settings();
    settings.set(HEADER_TABLE_SIZE, PERSIST_VALUE, 0);

    FramedConnection connection = sendHttp2SettingsAndCheckForAck(client, settings);

    // verify the peer's settings were read and applied.
    assertEquals(0, connection.peerSettings.getHeaderTableSize());
    Http2.Reader frameReader = (Http2.Reader) connection.readerRunnable.frameReader;
    assertEquals(0, frameReader.hpackReader.maxDynamicTableByteCount());
    // TODO: when supported, check the frameWriter's compression table is unaffected.
  }
Example #4
0
  private FramedConnection(Builder builder) throws IOException {
    protocol = builder.protocol;
    pushObserver = builder.pushObserver;
    client = builder.client;
    listener = builder.listener;
    // http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-5.1.1
    nextStreamId = builder.client ? 1 : 2;
    if (builder.client && protocol == Protocol.HTTP_2) {
      nextStreamId += 2; // In HTTP/2, 1 on client is reserved for Upgrade.
    }

    nextPingId = builder.client ? 1 : 2;

    // Flow control was designed more for servers, or proxies than edge clients.
    // If we are a client, set the flow control window to 16MiB.  This avoids
    // thrashing window updates every 64KiB, yet small enough to avoid blowing
    // up the heap.
    if (builder.client) {
      okHttpSettings.set(Settings.INITIAL_WINDOW_SIZE, 0, OKHTTP_CLIENT_WINDOW_SIZE);
    }

    hostname = builder.hostname;

    if (protocol == Protocol.HTTP_2) {
      variant = new Http2();
      // Like newSingleThreadExecutor, except lazy creates the thread.
      pushExecutor =
          new ThreadPoolExecutor(
              0,
              1,
              60,
              TimeUnit.SECONDS,
              new LinkedBlockingQueue<Runnable>(),
              Util.threadFactory(Util.format("OkHttp %s Push Observer", hostname), true));
      // 1 less than SPDY http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.9.2
      peerSettings.set(Settings.INITIAL_WINDOW_SIZE, 0, 65535);
      peerSettings.set(Settings.MAX_FRAME_SIZE, 0, Http2.INITIAL_MAX_FRAME_SIZE);
    } else if (protocol == Protocol.SPDY_3) {
      variant = new Spdy3();
      pushExecutor = null;
    } else {
      throw new AssertionError(protocol);
    }
    bytesLeftInWriteWindow = peerSettings.getInitialWindowSize(DEFAULT_INITIAL_WINDOW_SIZE);
    socket = builder.socket;
    frameWriter = variant.newWriter(builder.sink, client);

    readerRunnable = new Reader(variant.newReader(builder.source, client));
  }
Example #5
0
 /** Merges {@code settings} into this peer's settings and sends them to the remote peer. */
 public void setSettings(Settings settings) throws IOException {
   synchronized (frameWriter) {
     synchronized (this) {
       if (shutdown) {
         throw new IOException("shutdown");
       }
       okHttpSettings.merge(settings);
       frameWriter.settings(settings);
     }
   }
 }
Example #6
0
 /**
  * @param sendConnectionPreface true to send connection preface frames. This should always be true
  *     except for in tests that don't check for a connection preface.
  */
 void start(boolean sendConnectionPreface) throws IOException {
   if (sendConnectionPreface) {
     frameWriter.connectionPreface();
     frameWriter.settings(okHttpSettings);
     int windowSize = okHttpSettings.getInitialWindowSize(Settings.DEFAULT_INITIAL_WINDOW_SIZE);
     if (windowSize != Settings.DEFAULT_INITIAL_WINDOW_SIZE) {
       frameWriter.windowUpdate(0, windowSize - Settings.DEFAULT_INITIAL_WINDOW_SIZE);
     }
   }
   new Thread(readerRunnable).start(); // Not a daemon thread.
 }
Example #7
0
  @Test
  public void peerHttp2ServerLowersInitialWindowSize() throws Exception {
    peer.setVariantAndClient(HTTP_2, false);

    Settings initial = new Settings();
    initial.set(INITIAL_WINDOW_SIZE, PERSIST_VALUE, 1684);
    Settings shouldntImpactConnection = new Settings();
    shouldntImpactConnection.set(INITIAL_WINDOW_SIZE, PERSIST_VALUE, 3368);

    peer.sendFrame().settings(initial);
    peer.acceptFrame(); // ACK
    peer.sendFrame().settings(shouldntImpactConnection);
    peer.acceptFrame(); // ACK 2
    peer.acceptFrame(); // HEADERS
    peer.play();

    FramedConnection connection = connection(peer, HTTP_2);

    // Default is 64KiB - 1.
    assertEquals(65535, connection.peerSettings.getInitialWindowSize(-1));

    // Verify the peer received the ACK.
    MockSpdyPeer.InFrame ackFrame = peer.takeFrame();
    assertEquals(TYPE_SETTINGS, ackFrame.type);
    assertEquals(0, ackFrame.streamId);
    assertTrue(ackFrame.ack);
    ackFrame = peer.takeFrame();
    assertEquals(TYPE_SETTINGS, ackFrame.type);
    assertEquals(0, ackFrame.streamId);
    assertTrue(ackFrame.ack);

    // This stream was created *after* the connection settings were adjusted.
    FramedStream stream = connection.newStream(headerEntries("a", "android"), false, true);

    assertEquals(3368, connection.peerSettings.getInitialWindowSize(DEFAULT_INITIAL_WINDOW_SIZE));
    assertEquals(1684, connection.bytesLeftInWriteWindow); // initial wasn't affected.
    // New Stream is has the most recent initial window size.
    assertEquals(3368, stream.bytesLeftInWriteWindow);
  }
Example #8
0
 public synchronized int maxConcurrentStreams() {
   return peerSettings.getMaxConcurrentStreams(Integer.MAX_VALUE);
 }