17899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath/*
27899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Copyright (C) 2012 Square, Inc.
37899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath *
47899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
57899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * you may not use this file except in compliance with the License.
67899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * You may obtain a copy of the License at
77899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath *
87899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
97899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath *
107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Unless required by applicable law or agreed to in writing, software
117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * See the License for the specific language governing permissions and
147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * limitations under the License.
157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */
162231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonpackage com.squareup.okhttp.internal.spdy;
177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath
187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathfinal class Settings {
1954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /**
2054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * From the spdy/3 spec, the default initial window size for all streams is
2154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * 64 KiB. (Chrome 25 uses 10 MiB).
2254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   */
2354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024;
2454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
2554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Peer request to clear durable settings. */
2654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1;
2754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
2854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sent by servers only. The peer requests this setting persisted for future connections. */
2954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int PERSIST_VALUE = 0x1;
3054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sent by clients only. The client is reminding the server of a persisted value. */
3154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int PERSISTED = 0x2;
3254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
3354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sender's estimate of max incoming kbps. */
3454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int UPLOAD_BANDWIDTH = 0x1;
3554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sender's estimate of max outgoing kbps. */
3654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int DOWNLOAD_BANDWIDTH = 0x2;
3754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sender's estimate of milliseconds between sending a request and receiving a response. */
3854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int ROUND_TRIP_TIME = 0x3;
3954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Sender's maximum number of concurrent streams. */
4054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int MAX_CONCURRENT_STREAMS = 0x4;
4154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Current CWND in Packets. */
4254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int CURRENT_CWND = 0x5;
4354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Retransmission rate. Percentage */
4454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int DOWNLOAD_RETRANS_RATE = 0x6;
4554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Window size in bytes. */
4654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int INITIAL_WINDOW_SIZE = 0x7;
4754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Window size in bytes. */
4854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 0x8;
4954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Total number of settings. */
5054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  static final int COUNT = 0x9;
5154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
5254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Bitfield of which flags that values. */
5354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  private int set;
5454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
5554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Bitfield of flags that have {@link #PERSIST_VALUE}. */
5654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  private int persistValue;
5754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
5854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Bitfield of flags that have {@link #PERSISTED}. */
5954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  private int persisted;
6054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
6154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Flag values. */
6254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  private final int[] values = new int[COUNT];
6354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
6454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  void set(int id, int idFlags, int value) {
6554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    if (id >= values.length) {
6654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      return; // Discard unknown settings.
677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath    }
687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath
6954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << id;
7054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    set |= bit;
7154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    if ((idFlags & PERSIST_VALUE) != 0) {
7254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      persistValue |= bit;
7354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    } else {
7454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      persistValue &= ~bit;
757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath    }
7654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    if ((idFlags & PERSISTED) != 0) {
7754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      persisted |= bit;
7854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    } else {
7954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      persisted &= ~bit;
807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath    }
817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath
8254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    values[id] = value;
8354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
8454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
8554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Returns true if a value has been assigned for the setting {@code id}. */
8654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  boolean isSet(int id) {
8754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << id;
8854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (set & bit) != 0;
8954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
9054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
9154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Returns the value for the setting {@code id}, or 0 if unset. */
9254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int get(int id) {
9354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return values[id];
9454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
9554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
9654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Returns the flags for the setting {@code id}, or 0 if unset. */
9754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int flags(int id) {
9854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int result = 0;
9954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    if (isPersisted(id)) result |= Settings.PERSISTED;
10054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    if (persistValue(id)) result |= Settings.PERSIST_VALUE;
10154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return result;
10254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
10354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
10454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Returns the number of settings that have values assigned. */
10554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int size() {
10654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return Integer.bitCount(set);
10754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
10854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
10954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getUploadBandwidth(int defaultValue) {
11054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << UPLOAD_BANDWIDTH;
11154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue;
11254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
11354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
11454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getDownloadBandwidth(int defaultValue) {
11554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << DOWNLOAD_BANDWIDTH;
11654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue;
11754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
11854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
11954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getRoundTripTime(int defaultValue) {
12054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << ROUND_TRIP_TIME;
12154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue;
12254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
12354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
12454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getMaxConcurrentStreams(int defaultValue) {
12554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << MAX_CONCURRENT_STREAMS;
12654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue;
12754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
12854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
12954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getCurrentCwnd(int defaultValue) {
13054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << CURRENT_CWND;
13154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue;
13254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
13354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
13454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getDownloadRetransRate(int defaultValue) {
13554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << DOWNLOAD_RETRANS_RATE;
13654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue;
13754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
13854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
13954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getInitialWindowSize(int defaultValue) {
14054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << INITIAL_WINDOW_SIZE;
14154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue;
14254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
14354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
14454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  int getClientCertificateVectorSize(int defaultValue) {
14554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE;
14654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue;
14754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
14854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
14954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /**
15054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * Returns true if this user agent should use this setting in future SPDY
15154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * connections to the same host.
15254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   */
15354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  boolean persistValue(int id) {
15454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << id;
15554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (persistValue & bit) != 0;
15654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
15754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
15854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /** Returns true if this setting was persisted. */
15954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  boolean isPersisted(int id) {
16054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    int bit = 1 << id;
16154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    return (persisted & bit) != 0;
16254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
16354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson
16454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  /**
16554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * Writes {@code other} into this. If any setting is populated by this and
16654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   * {@code other}, the value and flags from {@code other} will be kept.
16754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson   */
16854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  void merge(Settings other) {
16954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson    for (int i = 0; i < COUNT; i++) {
17054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      if (!other.isSet(i)) continue;
17154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson      set(i, other.flags(i), other.get(i));
1727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath    }
17354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson  }
1747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath}
175