All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.netty.handler.codec.spdy.SpdySession Maven / Gradle / Ivy

Go to download

The Netty project is an effort to provide an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance and high scalability protocol servers and clients. In other words, Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

There is a newer version: 4.0.0.Alpha8
Show newest version
/*
 * 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 org.jboss.netty.handler.codec.spdy;

import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.netty.channel.MessageEvent;

final class SpdySession {

    private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed");

    private final Map activeStreams =
        new ConcurrentHashMap();

    int numActiveStreams() {
        return activeStreams.size();
    }

    boolean noActiveStreams() {
        return activeStreams.isEmpty();
    }

    boolean isActiveStream(int streamID) {
        return activeStreams.containsKey(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(
                    streamID,
                    new StreamState(priority, remoteSideClosed, localSideClosed, sendWindowSize, receiveWindowSize));
        }
    }

    void removeStream(int streamID) {
        Integer StreamID = streamID;
        StreamState state = activeStreams.get(StreamID);
        activeStreams.remove(StreamID);
        if (state != null) {
            MessageEvent e = state.removePendingWrite();
            while (e != null) {
                e.getFuture().setFailure(STREAM_CLOSED);
                e = state.removePendingWrite();
            }
        }
    }

    boolean isRemoteSideClosed(int streamID) {
        StreamState state = activeStreams.get(streamID);
        return state == null || state.isRemoteSideClosed();
    }

    void closeRemoteSide(int streamID) {
        Integer StreamID = 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(streamID);
        return state == null || state.isLocalSideClosed();
    }

    void closeLocalSide(int streamID) {
        Integer StreamID = 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(streamID);
        return state != null && state.hasReceivedReply();
    }

    void receivedReply(int streamID) {
        StreamState state = activeStreams.get(streamID);
        if (state != null) {
            state.receivedReply();
        }
    }

    int getSendWindowSize(int streamID) {
        StreamState state = activeStreams.get(streamID);
        return state != null ? state.getSendWindowSize() : -1;
    }

    int updateSendWindowSize(int streamID, int deltaWindowSize) {
        StreamState state = activeStreams.get(streamID);
        return state != null ? state.updateSendWindowSize(deltaWindowSize) : -1;
    }

    int updateReceiveWindowSize(int streamID, int deltaWindowSize) {
        StreamState state = activeStreams.get(streamID);
        if (deltaWindowSize > 0) {
            state.setReceiveWindowSizeLowerBound(0);
        }
        return state != null ? state.updateReceiveWindowSize(deltaWindowSize) : -1;
    }

    int getReceiveWindowSizeLowerBound(int streamID) {
        StreamState state = activeStreams.get(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, MessageEvent evt) {
        StreamState state = activeStreams.get(streamID);
        return state != null && state.putPendingWrite(evt);
    }

    MessageEvent getPendingWrite(int streamID) {
        StreamState state = activeStreams.get(streamID);
        return state != null ? state.getPendingWrite() : null;
    }

    MessageEvent removePendingWrite(int streamID) {
        StreamState state = activeStreams.get(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 ConcurrentLinkedQueue pendingWriteQueue =
                new ConcurrentLinkedQueue();

        StreamState(
                byte priority, boolean remoteSideClosed, boolean localSideClosed,
                int sendWindowSize, int receiveWindowSize) {
            this.priority = priority;
            this.remoteSideClosed = remoteSideClosed;
            this.localSideClosed = localSideClosed;
            this.sendWindowSize = new AtomicInteger(sendWindowSize);
            this.receiveWindowSize = new AtomicInteger(receiveWindowSize);
        }

        byte getPriority() {
            return priority;
        }

        boolean isRemoteSideClosed() {
            return remoteSideClosed;
        }

        void closeRemoteSide() {
            remoteSideClosed = true;
        }

        boolean isLocalSideClosed() {
            return localSideClosed;
        }

        void closeLocalSide() {
            localSideClosed = true;
        }

        boolean hasReceivedReply() {
            return receivedReply;
        }

        void receivedReply() {
            receivedReply = true;
        }

        int getSendWindowSize() {
            return sendWindowSize.get();
        }

        int updateSendWindowSize(int deltaWindowSize) {
            return sendWindowSize.addAndGet(deltaWindowSize);
        }

        int updateReceiveWindowSize(int deltaWindowSize) {
            return receiveWindowSize.addAndGet(deltaWindowSize);
        }

        int getReceiveWindowSizeLowerBound() {
            return receiveWindowSizeLowerBound;
        }

        void setReceiveWindowSizeLowerBound(int receiveWindowSizeLowerBound) {
            this.receiveWindowSizeLowerBound = receiveWindowSizeLowerBound;
        }

        boolean putPendingWrite(MessageEvent evt) {
            return pendingWriteQueue.offer(evt);
        }

        MessageEvent getPendingWrite() {
            return pendingWriteQueue.peek();
        }

        MessageEvent removePendingWrite() {
            return pendingWriteQueue.poll();
        }
    }

    private final class PriorityComparator implements Comparator {

        PriorityComparator() {
        }

        public int compare(Integer id1, Integer id2) {
            StreamState state1 = activeStreams.get(id1);
            StreamState state2 = activeStreams.get(id2);
            return state1.getPriority() - state2.getPriority();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy