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 */ 16package com.squareup.okhttp.internal.spdy; 17 18final class Settings { 19 /** 20 * From the spdy/3 spec, the default initial window size for all streams is 21 * 64 KiB. (Chrome 25 uses 10 MiB). 22 */ 23 static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024; 24 25 /** Peer request to clear durable settings. */ 26 static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1; 27 28 /** Sent by servers only. The peer requests this setting persisted for future connections. */ 29 static final int PERSIST_VALUE = 0x1; 30 /** Sent by clients only. The client is reminding the server of a persisted value. */ 31 static final int PERSISTED = 0x2; 32 33 /** Sender's estimate of max incoming kbps. */ 34 static final int UPLOAD_BANDWIDTH = 0x1; 35 /** Sender's estimate of max outgoing kbps. */ 36 static final int DOWNLOAD_BANDWIDTH = 0x2; 37 /** Sender's estimate of milliseconds between sending a request and receiving a response. */ 38 static final int ROUND_TRIP_TIME = 0x3; 39 /** Sender's maximum number of concurrent streams. */ 40 static final int MAX_CONCURRENT_STREAMS = 0x4; 41 /** Current CWND in Packets. */ 42 static final int CURRENT_CWND = 0x5; 43 /** Retransmission rate. Percentage */ 44 static final int DOWNLOAD_RETRANS_RATE = 0x6; 45 /** Window size in bytes. */ 46 static final int INITIAL_WINDOW_SIZE = 0x7; 47 /** Window size in bytes. */ 48 static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 0x8; 49 /** Total number of settings. */ 50 static final int COUNT = 0x9; 51 52 /** Bitfield of which flags that values. */ 53 private int set; 54 55 /** Bitfield of flags that have {@link #PERSIST_VALUE}. */ 56 private int persistValue; 57 58 /** Bitfield of flags that have {@link #PERSISTED}. */ 59 private int persisted; 60 61 /** Flag values. */ 62 private final int[] values = new int[COUNT]; 63 64 void set(int id, int idFlags, int value) { 65 if (id >= values.length) { 66 return; // Discard unknown settings. 67 } 68 69 int bit = 1 << id; 70 set |= bit; 71 if ((idFlags & PERSIST_VALUE) != 0) { 72 persistValue |= bit; 73 } else { 74 persistValue &= ~bit; 75 } 76 if ((idFlags & PERSISTED) != 0) { 77 persisted |= bit; 78 } else { 79 persisted &= ~bit; 80 } 81 82 values[id] = value; 83 } 84 85 /** Returns true if a value has been assigned for the setting {@code id}. */ 86 boolean isSet(int id) { 87 int bit = 1 << id; 88 return (set & bit) != 0; 89 } 90 91 /** Returns the value for the setting {@code id}, or 0 if unset. */ 92 int get(int id) { 93 return values[id]; 94 } 95 96 /** Returns the flags for the setting {@code id}, or 0 if unset. */ 97 int flags(int id) { 98 int result = 0; 99 if (isPersisted(id)) result |= Settings.PERSISTED; 100 if (persistValue(id)) result |= Settings.PERSIST_VALUE; 101 return result; 102 } 103 104 /** Returns the number of settings that have values assigned. */ 105 int size() { 106 return Integer.bitCount(set); 107 } 108 109 int getUploadBandwidth(int defaultValue) { 110 int bit = 1 << UPLOAD_BANDWIDTH; 111 return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue; 112 } 113 114 int getDownloadBandwidth(int defaultValue) { 115 int bit = 1 << DOWNLOAD_BANDWIDTH; 116 return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue; 117 } 118 119 int getRoundTripTime(int defaultValue) { 120 int bit = 1 << ROUND_TRIP_TIME; 121 return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue; 122 } 123 124 int getMaxConcurrentStreams(int defaultValue) { 125 int bit = 1 << MAX_CONCURRENT_STREAMS; 126 return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue; 127 } 128 129 int getCurrentCwnd(int defaultValue) { 130 int bit = 1 << CURRENT_CWND; 131 return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue; 132 } 133 134 int getDownloadRetransRate(int defaultValue) { 135 int bit = 1 << DOWNLOAD_RETRANS_RATE; 136 return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue; 137 } 138 139 int getInitialWindowSize(int defaultValue) { 140 int bit = 1 << INITIAL_WINDOW_SIZE; 141 return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue; 142 } 143 144 int getClientCertificateVectorSize(int defaultValue) { 145 int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE; 146 return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue; 147 } 148 149 /** 150 * Returns true if this user agent should use this setting in future SPDY 151 * connections to the same host. 152 */ 153 boolean persistValue(int id) { 154 int bit = 1 << id; 155 return (persistValue & bit) != 0; 156 } 157 158 /** Returns true if this setting was persisted. */ 159 boolean isPersisted(int id) { 160 int bit = 1 << id; 161 return (persisted & bit) != 0; 162 } 163 164 /** 165 * Writes {@code other} into this. If any setting is populated by this and 166 * {@code other}, the value and flags from {@code other} will be kept. 167 */ 168 void merge(Settings other) { 169 for (int i = 0; i < COUNT; i++) { 170 if (!other.isSet(i)) continue; 171 set(i, other.flags(i), other.get(i)); 172 } 173 } 174} 175