View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.spdy;
20  
21  import java.util.concurrent.TimeUnit;
22  
23  import org.eclipse.jetty.spdy.api.DataInfo;
24  import org.eclipse.jetty.spdy.api.Stream;
25  import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
26  import org.eclipse.jetty.util.Callback;
27  
28  public class SPDYv3FlowControlStrategy implements FlowControlStrategy
29  {
30      private volatile int windowSize;
31  
32      @Override
33      public int getWindowSize(ISession session)
34      {
35          return windowSize;
36      }
37  
38      @Override
39      public void setWindowSize(ISession session, int windowSize)
40      {
41          int prevWindowSize = this.windowSize;
42          this.windowSize = windowSize;
43          for (Stream stream : session.getStreams())
44              ((IStream)stream).updateWindowSize(windowSize - prevWindowSize);
45      }
46  
47      @Override
48      public void onNewStream(ISession session, IStream stream)
49      {
50          stream.updateWindowSize(windowSize);
51      }
52  
53      @Override
54      public void onWindowUpdate(ISession session, IStream stream, int delta)
55      {
56          if (stream != null)
57              stream.updateWindowSize(delta);
58      }
59  
60      @Override
61      public void updateWindow(ISession session, IStream stream, int delta)
62      {
63          stream.updateWindowSize(delta);
64      }
65  
66      @Override
67      public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo)
68      {
69          // Do nothing
70      }
71  
72      @Override
73      public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta)
74      {
75          // This is the algorithm for flow control.
76          // This method may be called multiple times with delta=1, but we only send a window
77          // update when the whole dataInfo has been consumed.
78          // Other policies may be to send window updates when consumed() is greater than
79          // a certain threshold, etc. but for now the policy is not pluggable for simplicity.
80          // Note that the frequency of window updates depends on the read buffer, that
81          // should not be too smaller than the window size to avoid frequent window updates.
82          // Therefore, a pluggable policy should be able to modify the read buffer capacity.
83          int length = dataInfo.length();
84          if (dataInfo.consumed() == length && !stream.isClosed() && length > 0)
85          {
86              WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(), stream.getId(), length);
87              session.control(stream, windowUpdateFrame, 0, TimeUnit.MILLISECONDS, new Callback.Adapter());
88          }
89      }
90  }