/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.coyote.http2;
import java.util.Map;
Represents the local connection settings i.e. the settings the client is
expected to use when communicating with the server. There will be a delay
between calling a setter and the setting taking effect at the client. When a
setter is called, the new value is added to the set of pending settings. Once
the ACK is received, the new value is moved to the current settings. While
waiting for the ACK, the getters will return the most lenient / generous /
relaxed of the current setting and the pending setting. This class does not
validate the values passed to the setters. If an invalid value is used the
client will respond (almost certainly by closing the connection) as defined
in the HTTP/2 specification.
/**
* Represents the local connection settings i.e. the settings the client is
* expected to use when communicating with the server. There will be a delay
* between calling a setter and the setting taking effect at the client. When a
* setter is called, the new value is added to the set of pending settings. Once
* the ACK is received, the new value is moved to the current settings. While
* waiting for the ACK, the getters will return the most lenient / generous /
* relaxed of the current setting and the pending setting. This class does not
* validate the values passed to the setters. If an invalid value is used the
* client will respond (almost certainly by closing the connection) as defined
* in the HTTP/2 specification.
*/
class ConnectionSettingsLocal extends ConnectionSettingsBase<IllegalArgumentException> {
private static final String ENDPOINT_NAME = "Local(client->server)";
private boolean sendInProgress = false;
ConnectionSettingsLocal(String connectionId) {
super(connectionId);
}
@Override
final synchronized void set(Setting setting, Long value) {
checkSend();
if (current.get(setting).longValue() == value.longValue()) {
pending.remove(setting);
} else {
pending.put(setting, value);
}
}
final synchronized byte[] getSettingsFrameForPending() {
checkSend();
int payloadSize = pending.size() * 6;
byte[] result = new byte[9 + payloadSize];
ByteUtil.setThreeBytes(result, 0, payloadSize);
result[3] = FrameType.SETTINGS.getIdByte();
// No flags
// Stream is zero
// Payload
int pos = 9;
for (Map.Entry<Setting,Long> setting : pending.entrySet()) {
ByteUtil.setTwoBytes(result, pos, setting.getKey().getId());
pos += 2;
ByteUtil.setFourBytes(result, pos, setting.getValue().longValue());
pos += 4;
}
sendInProgress = true;
return result;
}
final synchronized boolean ack() {
if (sendInProgress) {
sendInProgress = false;
current.putAll(pending);
pending.clear();
return true;
} else {
return false;
}
}
private void checkSend() {
if (sendInProgress) {
// Coding error. No need for i18n
throw new IllegalStateException();
}
}
@Override
final void throwException(String msg, Http2Error error) throws IllegalArgumentException {
throw new IllegalArgumentException(msg);
}
@Override
final String getEndpointName() {
return ENDPOINT_NAME;
}
}