• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.framed;
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 FramedConnection connection} scoped.
23  */
24 public 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: The peer 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   /** HTTP/2: Size in bytes of the largest frame payload the sender will accept. */
54   static final int MAX_FRAME_SIZE = 5;
55   /** spdy/3: Retransmission rate. Percentage */
56   static final int DOWNLOAD_RETRANS_RATE = 6;
57   /** HTTP/2: Advisory only. Size in bytes of the largest header list the sender will accept. */
58   static final int MAX_HEADER_LIST_SIZE = 6;
59   /** Window size in bytes. */
60   static final int INITIAL_WINDOW_SIZE = 7;
61   /** spdy/3: Size of the client certificate vector. Unsupported. */
62   static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 8;
63   /** Flow control options. */
64   static final int FLOW_CONTROL_OPTIONS = 10;
65 
66   /** Total number of settings. */
67   static final int COUNT = 10;
68 
69   /** If set, flow control is disabled for streams directed to the sender of these settings. */
70   static final int FLOW_CONTROL_OPTIONS_DISABLED = 0x1;
71 
72   /** Bitfield of which flags that values. */
73   private int set;
74 
75   /** Bitfield of flags that have {@link #PERSIST_VALUE}. */
76   private int persistValue;
77 
78   /** Bitfield of flags that have {@link #PERSISTED}. */
79   private int persisted;
80 
81   /** Flag values. */
82   private final int[] values = new int[COUNT];
83 
clear()84   void clear() {
85     set = persistValue = persisted = 0;
86     Arrays.fill(values, 0);
87   }
88 
set(int id, int idFlags, int value)89   Settings set(int id, int idFlags, int value) {
90     if (id >= values.length) {
91       return this; // Discard unknown settings.
92     }
93 
94     int bit = 1 << id;
95     set |= bit;
96     if ((idFlags & PERSIST_VALUE) != 0) {
97       persistValue |= bit;
98     } else {
99       persistValue &= ~bit;
100     }
101     if ((idFlags & PERSISTED) != 0) {
102       persisted |= bit;
103     } else {
104       persisted &= ~bit;
105     }
106 
107     values[id] = value;
108     return this;
109   }
110 
111   /** Returns true if a value has been assigned for the setting {@code id}. */
isSet(int id)112   boolean isSet(int id) {
113     int bit = 1 << id;
114     return (set & bit) != 0;
115   }
116 
117   /** Returns the value for the setting {@code id}, or 0 if unset. */
get(int id)118   int get(int id) {
119     return values[id];
120   }
121 
122   /** Returns the flags for the setting {@code id}, or 0 if unset. */
flags(int id)123   int flags(int id) {
124     int result = 0;
125     if (isPersisted(id)) result |= Settings.PERSISTED;
126     if (persistValue(id)) result |= Settings.PERSIST_VALUE;
127     return result;
128   }
129 
130   /** Returns the number of settings that have values assigned. */
size()131   int size() {
132     return Integer.bitCount(set);
133   }
134 
135   /** spdy/3 only. */
getUploadBandwidth(int defaultValue)136   int getUploadBandwidth(int defaultValue) {
137     int bit = 1 << UPLOAD_BANDWIDTH;
138     return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue;
139   }
140 
141   /** HTTP/2 only. Returns -1 if unset. */
getHeaderTableSize()142   int getHeaderTableSize() {
143     int bit = 1 << HEADER_TABLE_SIZE;
144     return (bit & set) != 0 ? values[HEADER_TABLE_SIZE] : -1;
145   }
146 
147   /** spdy/3 only. */
getDownloadBandwidth(int defaultValue)148   int getDownloadBandwidth(int defaultValue) {
149     int bit = 1 << DOWNLOAD_BANDWIDTH;
150     return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue;
151   }
152 
153   /** HTTP/2 only. */
154   // TODO: honor this setting in HTTP/2.
getEnablePush(boolean defaultValue)155   boolean getEnablePush(boolean defaultValue) {
156     int bit = 1 << ENABLE_PUSH;
157     return ((bit & set) != 0 ? values[ENABLE_PUSH] : defaultValue ? 1 : 0) == 1;
158   }
159 
160   /** spdy/3 only. */
getRoundTripTime(int defaultValue)161   int getRoundTripTime(int defaultValue) {
162     int bit = 1 << ROUND_TRIP_TIME;
163     return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue;
164   }
165 
166   // TODO: honor this setting in spdy/3 and HTTP/2.
getMaxConcurrentStreams(int defaultValue)167   int getMaxConcurrentStreams(int defaultValue) {
168     int bit = 1 << MAX_CONCURRENT_STREAMS;
169     return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue;
170   }
171 
172   /** spdy/3 only. */
getCurrentCwnd(int defaultValue)173   int getCurrentCwnd(int defaultValue) {
174     int bit = 1 << CURRENT_CWND;
175     return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue;
176   }
177 
178   /** HTTP/2 only. */
getMaxFrameSize(int defaultValue)179   int getMaxFrameSize(int defaultValue) {
180     int bit = 1 << MAX_FRAME_SIZE;
181     return (bit & set) != 0 ? values[MAX_FRAME_SIZE] : defaultValue;
182   }
183 
184   /** spdy/3 only. */
getDownloadRetransRate(int defaultValue)185   int getDownloadRetransRate(int defaultValue) {
186     int bit = 1 << DOWNLOAD_RETRANS_RATE;
187     return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue;
188   }
189 
190   /** HTTP/2 only. */
getMaxHeaderListSize(int defaultValue)191   int getMaxHeaderListSize(int defaultValue) {
192     int bit = 1 << MAX_HEADER_LIST_SIZE;
193     return (bit & set) != 0 ? values[MAX_HEADER_LIST_SIZE] : defaultValue;
194   }
195 
getInitialWindowSize(int defaultValue)196   int getInitialWindowSize(int defaultValue) {
197     int bit = 1 << INITIAL_WINDOW_SIZE;
198     return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue;
199   }
200 
201   /** spdy/3 only. */
getClientCertificateVectorSize(int defaultValue)202   int getClientCertificateVectorSize(int defaultValue) {
203     int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE;
204     return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue;
205   }
206 
207   // TODO: honor this setting in spdy/3 and HTTP/2.
isFlowControlDisabled()208   boolean isFlowControlDisabled() {
209     int bit = 1 << FLOW_CONTROL_OPTIONS;
210     int value = (bit & set) != 0 ? values[FLOW_CONTROL_OPTIONS] : 0;
211     return (value & FLOW_CONTROL_OPTIONS_DISABLED) != 0;
212   }
213 
214   /**
215    * Returns true if this user agent should use this setting in future spdy/3
216    * connections to the same host.
217    */
persistValue(int id)218   boolean persistValue(int id) {
219     int bit = 1 << id;
220     return (persistValue & bit) != 0;
221   }
222 
223   /** Returns true if this setting was persisted. */
isPersisted(int id)224   boolean isPersisted(int id) {
225     int bit = 1 << id;
226     return (persisted & bit) != 0;
227   }
228 
229   /**
230    * Writes {@code other} into this. If any setting is populated by this and
231    * {@code other}, the value and flags from {@code other} will be kept.
232    */
merge(Settings other)233   void merge(Settings other) {
234     for (int i = 0; i < COUNT; i++) {
235       if (!other.isSet(i)) continue;
236       set(i, other.flags(i), other.get(i));
237     }
238   }
239 }
240