Home | History | Annotate | Download | only in spdy
      1 /*
      2  * Copyright (C) 2012 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.squareup.okhttp.internal.spdy;
     17 
     18 import java.util.Arrays;
     19 
     20 /**
     21  * Settings describe characteristics of the sending peer, which are used by the receiving peer.
     22  * Settings are {@link com.squareup.okhttp.internal.spdy.SpdyConnection connection} scoped.
     23  */
     24 final class Settings {
     25   /**
     26    * From the SPDY/3 and HTTP/2 specs, the default initial window size for all
     27    * streams is 64 KiB. (Chrome 25 uses 10 MiB).
     28    */
     29   static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024;
     30 
     31   /** Peer request to clear durable settings. */
     32   static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1;
     33 
     34   /** Sent by servers only. The peer requests this setting persisted for future connections. */
     35   static final int PERSIST_VALUE = 0x1;
     36   /** Sent by clients only. The client is reminding the server of a persisted value. */
     37   static final int PERSISTED = 0x2;
     38 
     39   /** spdy/3: Sender's estimate of max incoming kbps. */
     40   static final int UPLOAD_BANDWIDTH = 1;
     41   /** http/2: Size in bytes of the table used to decode the sender's header blocks. */
     42   static final int HEADER_TABLE_SIZE = 1;
     43   /** spdy/3: Sender's estimate of max outgoing kbps. */
     44   static final int DOWNLOAD_BANDWIDTH = 2;
     45   /** http/2: An endpoint must not send a PUSH_PROMISE frame when this is 0. */
     46   static final int ENABLE_PUSH = 2;
     47   /** spdy/3: Sender's estimate of millis between sending a request and receiving a response. */
     48   static final int ROUND_TRIP_TIME = 3;
     49   /** Sender's maximum number of concurrent streams. */
     50   static final int MAX_CONCURRENT_STREAMS = 4;
     51   /** spdy/3: Current CWND in Packets. */
     52   static final int CURRENT_CWND = 5;
     53   /** spdy/3: Retransmission rate. Percentage */
     54   static final int DOWNLOAD_RETRANS_RATE = 6;
     55   /** Window size in bytes. */
     56   static final int INITIAL_WINDOW_SIZE = 7;
     57   /** spdy/3: Window size in bytes. */
     58   static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 8;
     59   /** Flow control options. */
     60   static final int FLOW_CONTROL_OPTIONS = 10;
     61 
     62   /** Total number of settings. */
     63   static final int COUNT = 10;
     64 
     65   /** If set, flow control is disabled for streams directed to the sender of these settings. */
     66   static final int FLOW_CONTROL_OPTIONS_DISABLED = 0x1;
     67 
     68   /** Bitfield of which flags that values. */
     69   private int set;
     70 
     71   /** Bitfield of flags that have {@link #PERSIST_VALUE}. */
     72   private int persistValue;
     73 
     74   /** Bitfield of flags that have {@link #PERSISTED}. */
     75   private int persisted;
     76 
     77   /** Flag values. */
     78   private final int[] values = new int[COUNT];
     79 
     80   void clear() {
     81     set = persistValue = persisted = 0;
     82     Arrays.fill(values, 0);
     83   }
     84 
     85   Settings set(int id, int idFlags, int value) {
     86     if (id >= values.length) {
     87       return this; // Discard unknown settings.
     88     }
     89 
     90     int bit = 1 << id;
     91     set |= bit;
     92     if ((idFlags & PERSIST_VALUE) != 0) {
     93       persistValue |= bit;
     94     } else {
     95       persistValue &= ~bit;
     96     }
     97     if ((idFlags & PERSISTED) != 0) {
     98       persisted |= bit;
     99     } else {
    100       persisted &= ~bit;
    101     }
    102 
    103     values[id] = value;
    104     return this;
    105   }
    106 
    107   /** Returns true if a value has been assigned for the setting {@code id}. */
    108   boolean isSet(int id) {
    109     int bit = 1 << id;
    110     return (set & bit) != 0;
    111   }
    112 
    113   /** Returns the value for the setting {@code id}, or 0 if unset. */
    114   int get(int id) {
    115     return values[id];
    116   }
    117 
    118   /** Returns the flags for the setting {@code id}, or 0 if unset. */
    119   int flags(int id) {
    120     int result = 0;
    121     if (isPersisted(id)) result |= Settings.PERSISTED;
    122     if (persistValue(id)) result |= Settings.PERSIST_VALUE;
    123     return result;
    124   }
    125 
    126   /** Returns the number of settings that have values assigned. */
    127   int size() {
    128     return Integer.bitCount(set);
    129   }
    130 
    131   /** spdy/3 only. */
    132   int getUploadBandwidth(int defaultValue) {
    133     int bit = 1 << UPLOAD_BANDWIDTH;
    134     return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue;
    135   }
    136 
    137   /** http/2 only. Returns -1 if unset. */
    138   int getHeaderTableSize() {
    139     int bit = 1 << HEADER_TABLE_SIZE;
    140     return (bit & set) != 0 ? values[HEADER_TABLE_SIZE] : -1;
    141   }
    142 
    143   /** spdy/3 only. */
    144   int getDownloadBandwidth(int defaultValue) {
    145     int bit = 1 << DOWNLOAD_BANDWIDTH;
    146     return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue;
    147   }
    148 
    149   /** http/2 only. */
    150   // TODO: honor this setting in http/2.
    151   boolean getEnablePush(boolean defaultValue) {
    152     int bit = 1 << ENABLE_PUSH;
    153     return ((bit & set) != 0 ? values[ENABLE_PUSH] : defaultValue ? 1 : 0) == 1;
    154   }
    155 
    156   /** spdy/3 only. */
    157   int getRoundTripTime(int defaultValue) {
    158     int bit = 1 << ROUND_TRIP_TIME;
    159     return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue;
    160   }
    161 
    162   // TODO: honor this setting in spdy/3 and http/2.
    163   int getMaxConcurrentStreams(int defaultValue) {
    164     int bit = 1 << MAX_CONCURRENT_STREAMS;
    165     return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue;
    166   }
    167 
    168   /** spdy/3 only. */
    169   int getCurrentCwnd(int defaultValue) {
    170     int bit = 1 << CURRENT_CWND;
    171     return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue;
    172   }
    173 
    174   /** spdy/3 only. */
    175   int getDownloadRetransRate(int defaultValue) {
    176     int bit = 1 << DOWNLOAD_RETRANS_RATE;
    177     return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue;
    178   }
    179 
    180   int getInitialWindowSize(int defaultValue) {
    181     int bit = 1 << INITIAL_WINDOW_SIZE;
    182     return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue;
    183   }
    184 
    185   /** spdy/3 only. */
    186   int getClientCertificateVectorSize(int defaultValue) {
    187     int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE;
    188     return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue;
    189   }
    190 
    191   // TODO: honor this setting in spdy/3 and http/2.
    192   boolean isFlowControlDisabled() {
    193     int bit = 1 << FLOW_CONTROL_OPTIONS;
    194     int value = (bit & set) != 0 ? values[FLOW_CONTROL_OPTIONS] : 0;
    195     return (value & FLOW_CONTROL_OPTIONS_DISABLED) != 0;
    196   }
    197 
    198   /**
    199    * Returns true if this user agent should use this setting in future spdy/3
    200    * connections to the same host.
    201    */
    202   boolean persistValue(int id) {
    203     int bit = 1 << id;
    204     return (persistValue & bit) != 0;
    205   }
    206 
    207   /** Returns true if this setting was persisted. */
    208   boolean isPersisted(int id) {
    209     int bit = 1 << id;
    210     return (persisted & bit) != 0;
    211   }
    212 
    213   /**
    214    * Writes {@code other} into this. If any setting is populated by this and
    215    * {@code other}, the value and flags from {@code other} will be kept.
    216    */
    217   void merge(Settings other) {
    218     for (int i = 0; i < COUNT; i++) {
    219       if (!other.isSet(i)) continue;
    220       set(i, other.flags(i), other.get(i));
    221     }
    222   }
    223 }
    224