/*
* Copyright (C) 2012 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.http2;
import java.util.
Arrays;
/**
* Settings describe characteristics of the sending peer, which are used by the receiving peer.
* Settings are {@link Http2Connection connection} scoped.
*/
public final class
Settings {
/**
* From the HTTP/2 specs, the default initial window size for all streams is 64 KiB. (Chrome 25
* uses 10 MiB).
*/
static final int
DEFAULT_INITIAL_WINDOW_SIZE = 65535;
/** HTTP/2: Size in bytes of the table used to decode the sender's header blocks. */
static final int
HEADER_TABLE_SIZE = 1;
/** HTTP/2: The peer must not send a PUSH_PROMISE frame when this is 0. */
static final int
ENABLE_PUSH = 2;
/** Sender's maximum number of concurrent streams. */
static final int
MAX_CONCURRENT_STREAMS = 4;
/** HTTP/2: Size in bytes of the largest frame payload the sender will accept. */
static final int
MAX_FRAME_SIZE = 5;
/** HTTP/2: Advisory only. Size in bytes of the largest header list the sender will accept. */
static final int
MAX_HEADER_LIST_SIZE = 6;
/** Window size in bytes. */
static final int
INITIAL_WINDOW_SIZE = 7;
/** Total number of settings. */
static final int
COUNT = 10;
/** Bitfield of which flags that values. */
private int
set;
/** Flag values. */
private final int[]
values = new int[
COUNT];
void
clear() {
set = 0;
Arrays.
fill(
values, 0);
}
Settings set(int
id, int
value) {
if (
id < 0 ||
id >=
values.length) {
return this; // Discard unknown settings.
}
int
bit = 1 <<
id;
set |=
bit;
values[
id] =
value;
return this;
}
/** Returns true if a value has been assigned for the setting {@code id}. */
boolean
isSet(int
id) {
int
bit = 1 <<
id;
return (
set &
bit) != 0;
}
/** Returns the value for the setting {@code id}, or 0 if unset. */
int
get(int
id) {
return
values[
id];
}
/** Returns the number of settings that have values assigned. */
int
size() {
return
Integer.
bitCount(
set);
}
/** Returns -1 if unset. */
int
getHeaderTableSize() {
int
bit = 1 <<
HEADER_TABLE_SIZE;
return (
bit &
set) != 0 ?
values[
HEADER_TABLE_SIZE] : -1;
}
// TODO: honor this setting.
boolean
getEnablePush(boolean
defaultValue) {
int
bit = 1 <<
ENABLE_PUSH;
return ((
bit &
set) != 0 ?
values[
ENABLE_PUSH] :
defaultValue ? 1 : 0) == 1;
}
int
getMaxConcurrentStreams(int
defaultValue) {
int
bit = 1 <<
MAX_CONCURRENT_STREAMS;
return (
bit &
set) != 0 ?
values[
MAX_CONCURRENT_STREAMS] :
defaultValue;
}
int
getMaxFrameSize(int
defaultValue) {
int
bit = 1 <<
MAX_FRAME_SIZE;
return (
bit &
set) != 0 ?
values[
MAX_FRAME_SIZE] :
defaultValue;
}
int
getMaxHeaderListSize(int
defaultValue) {
int
bit = 1 <<
MAX_HEADER_LIST_SIZE;
return (
bit &
set) != 0 ?
values[
MAX_HEADER_LIST_SIZE] :
defaultValue;
}
int
getInitialWindowSize() {
int
bit = 1 <<
INITIAL_WINDOW_SIZE;
return (
bit &
set) != 0 ?
values[
INITIAL_WINDOW_SIZE] :
DEFAULT_INITIAL_WINDOW_SIZE;
}
/**
* Writes {@code other} into this. If any setting is populated by this and {@code other}, the
* value and flags from {@code other} will be kept.
*/
void
merge(
Settings other) {
for (int
i = 0;
i <
COUNT;
i++) {
if (!
other.
isSet(
i)) continue;
set(
i,
other.
get(
i));
}
}
}