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 }