io.netty.handler.codec.spdy.SpdySession Maven / Gradle / Ivy
/*
* Copyright 2012 The Netty Project
*
* The Netty Project 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 io.netty.handler.codec.spdy;
import io.netty.util.internal.PlatformDependent;
import java.util.Comparator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
final class SpdySession {
private final Map activeStreams = PlatformDependent.newConcurrentHashMap();
int numActiveStreams() {
return activeStreams.size();
}
boolean noActiveStreams() {
return activeStreams.isEmpty();
}
boolean isActiveStream(int streamID) {
return activeStreams.containsKey(Integer.valueOf(streamID));
}
// Stream-IDs should be iterated in priority order
Set getActiveStreams() {
TreeSet StreamIDs = new TreeSet(new PriorityComparator());
StreamIDs.addAll(activeStreams.keySet());
return StreamIDs;
}
void acceptStream(
int streamID, byte priority, boolean remoteSideClosed, boolean localSideClosed,
int sendWindowSize, int receiveWindowSize) {
if (!remoteSideClosed || !localSideClosed) {
activeStreams.put(
Integer.valueOf(streamID),
new StreamState(priority, remoteSideClosed, localSideClosed, sendWindowSize, receiveWindowSize));
}
}
boolean removeStream(int streamID) {
Integer StreamID = Integer.valueOf(streamID);
StreamState state = activeStreams.get(StreamID);
activeStreams.remove(StreamID);
if (state != null) {
return state.clearPendingWrites();
} else {
return false;
}
}
boolean isRemoteSideClosed(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state == null || state.isRemoteSideClosed();
}
void closeRemoteSide(int streamID) {
Integer StreamID = Integer.valueOf(streamID);
StreamState state = activeStreams.get(StreamID);
if (state != null) {
state.closeRemoteSide();
if (state.isLocalSideClosed()) {
activeStreams.remove(StreamID);
}
}
}
boolean isLocalSideClosed(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state == null || state.isLocalSideClosed();
}
void closeLocalSide(int streamID) {
Integer StreamID = Integer.valueOf(streamID);
StreamState state = activeStreams.get(StreamID);
if (state != null) {
state.closeLocalSide();
if (state.isRemoteSideClosed()) {
activeStreams.remove(StreamID);
}
}
}
/*
* hasReceivedReply and receivedReply are only called from messageReceived
* no need to synchronize access to the StreamState
*/
boolean hasReceivedReply(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null && state.hasReceivedReply();
}
void receivedReply(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
if (state != null) {
state.receivedReply();
}
}
int getSendWindowSize(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null ? state.getSendWindowSize() : -1;
}
int updateSendWindowSize(int streamID, int deltaWindowSize) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null ? state.updateSendWindowSize(deltaWindowSize) : -1;
}
int updateReceiveWindowSize(int streamID, int deltaWindowSize) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
if (deltaWindowSize > 0) {
state.setReceiveWindowSizeLowerBound(0);
}
return state != null ? state.updateReceiveWindowSize(deltaWindowSize) : -1;
}
int getReceiveWindowSizeLowerBound(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null ? state.getReceiveWindowSizeLowerBound() : 0;
}
void updateAllReceiveWindowSizes(int deltaWindowSize) {
for (StreamState state: activeStreams.values()) {
state.updateReceiveWindowSize(deltaWindowSize);
if (deltaWindowSize < 0) {
state.setReceiveWindowSizeLowerBound(deltaWindowSize);
}
}
}
boolean putPendingWrite(int streamID, Object msg) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null && state.putPendingWrite(msg);
}
Object getPendingWrite(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null ? state.getPendingWrite() : null;
}
Object removePendingWrite(int streamID) {
StreamState state = activeStreams.get(Integer.valueOf(streamID));
return state != null ? state.removePendingWrite() : null;
}
private static final class StreamState {
private final byte priority;
private volatile boolean remoteSideClosed;
private volatile boolean localSideClosed;
private boolean receivedReply;
private final AtomicInteger sendWindowSize;
private final AtomicInteger receiveWindowSize;
private volatile int receiveWindowSizeLowerBound;
private final Queue