1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http2.server;
20
21 import java.util.Objects;
22
23 import org.eclipse.jetty.http2.BufferingFlowControlStrategy;
24 import org.eclipse.jetty.http2.FlowControlStrategy;
25 import org.eclipse.jetty.http2.HTTP2Connection;
26 import org.eclipse.jetty.http2.api.server.ServerSessionListener;
27 import org.eclipse.jetty.http2.generator.Generator;
28 import org.eclipse.jetty.http2.parser.ServerParser;
29 import org.eclipse.jetty.io.Connection;
30 import org.eclipse.jetty.io.EndPoint;
31 import org.eclipse.jetty.server.AbstractConnectionFactory;
32 import org.eclipse.jetty.server.Connector;
33 import org.eclipse.jetty.server.HttpConfiguration;
34 import org.eclipse.jetty.util.annotation.ManagedAttribute;
35 import org.eclipse.jetty.util.annotation.ManagedObject;
36 import org.eclipse.jetty.util.annotation.Name;
37 import org.eclipse.jetty.util.component.LifeCycle;
38 import org.eclipse.jetty.util.thread.ExecutionStrategy;
39 import org.eclipse.jetty.util.thread.strategy.ProduceExecuteConsume;
40
41 @ManagedObject
42 public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
43 {
44 private final Connection.Listener connectionListener = new ConnectionListener();
45 private final HttpConfiguration httpConfiguration;
46 private int maxDynamicTableSize = 4096;
47 private int initialStreamRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
48 private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
49 private int maxConcurrentStreams = 128;
50 private int maxHeaderBlockFragment = 0;
51 private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
52 private ExecutionStrategy.Factory executionStrategyFactory = new ProduceExecuteConsume.Factory();
53 private long streamIdleTimeout;
54
55 public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
56 {
57 this(httpConfiguration,"h2","h2-17","h2-16","h2-15","h2-14");
58 }
59
60 protected AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration, String... protocols)
61 {
62 super(protocols);
63 this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
64 addBean(httpConfiguration);
65 }
66
67 @ManagedAttribute("The HPACK dynamic table maximum size")
68 public int getMaxDynamicTableSize()
69 {
70 return maxDynamicTableSize;
71 }
72
73 public void setMaxDynamicTableSize(int maxDynamicTableSize)
74 {
75 this.maxDynamicTableSize = maxDynamicTableSize;
76 }
77
78 @ManagedAttribute("The initial size of session's flow control receive window")
79 public int getInitialSessionRecvWindow()
80 {
81 return initialSessionRecvWindow;
82 }
83
84 public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
85 {
86 this.initialSessionRecvWindow = initialSessionRecvWindow;
87 }
88
89 @ManagedAttribute("The initial size of stream's flow control receive window")
90 public int getInitialStreamRecvWindow()
91 {
92 return initialStreamRecvWindow;
93 }
94
95 public void setInitialStreamRecvWindow(int initialStreamRecvWindow)
96 {
97 this.initialStreamRecvWindow = initialStreamRecvWindow;
98 }
99
100
101
102
103
104 @Deprecated
105 public int getInitialStreamSendWindow()
106 {
107 return getInitialStreamRecvWindow();
108 }
109
110
111
112
113
114 @Deprecated
115 public void setInitialStreamSendWindow(int initialStreamSendWindow)
116 {
117 setInitialStreamRecvWindow(initialStreamSendWindow);
118 }
119
120 @ManagedAttribute("The max number of concurrent streams per session")
121 public int getMaxConcurrentStreams()
122 {
123 return maxConcurrentStreams;
124 }
125
126 public void setMaxConcurrentStreams(int maxConcurrentStreams)
127 {
128 this.maxConcurrentStreams = maxConcurrentStreams;
129 }
130
131 public int getMaxHeaderBlockFragment()
132 {
133 return maxHeaderBlockFragment;
134 }
135
136 public void setMaxHeaderBlockFragment(int maxHeaderBlockFragment)
137 {
138 this.maxHeaderBlockFragment = maxHeaderBlockFragment;
139 }
140
141 public FlowControlStrategy.Factory getFlowControlStrategyFactory()
142 {
143 return flowControlStrategyFactory;
144 }
145
146 public void setFlowControlStrategyFactory(FlowControlStrategy.Factory flowControlStrategyFactory)
147 {
148 this.flowControlStrategyFactory = flowControlStrategyFactory;
149 }
150
151 public ExecutionStrategy.Factory getExecutionStrategyFactory()
152 {
153 return executionStrategyFactory;
154 }
155
156 public void setExecutionStrategyFactory(ExecutionStrategy.Factory executionStrategyFactory)
157 {
158 this.executionStrategyFactory = executionStrategyFactory;
159 }
160
161 @ManagedAttribute("The stream idle timeout in milliseconds")
162 public long getStreamIdleTimeout()
163 {
164 return streamIdleTimeout;
165 }
166
167 public void setStreamIdleTimeout(long streamIdleTimeout)
168 {
169 this.streamIdleTimeout = streamIdleTimeout;
170 }
171
172 public HttpConfiguration getHttpConfiguration()
173 {
174 return httpConfiguration;
175 }
176
177 @Override
178 public Connection newConnection(Connector connector, EndPoint endPoint)
179 {
180 ServerSessionListener listener = newSessionListener(connector, endPoint);
181
182 Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
183 FlowControlStrategy flowControl = newFlowControlStrategy();
184 if (flowControl == null)
185 flowControl = getFlowControlStrategyFactory().newFlowControlStrategy();
186 HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl);
187 session.setMaxLocalStreams(getMaxConcurrentStreams());
188 session.setMaxRemoteStreams(getMaxConcurrentStreams());
189
190
191
192
193 long streamIdleTimeout = getStreamIdleTimeout();
194 if (streamIdleTimeout <= 0)
195 streamIdleTimeout = endPoint.getIdleTimeout();
196 session.setStreamIdleTimeout(streamIdleTimeout);
197 session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
198
199 ServerParser parser = newServerParser(connector, session);
200 HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
201 endPoint, httpConfiguration, parser, session, getInputBufferSize(), getExecutionStrategyFactory(), listener);
202 connection.addListener(connectionListener);
203 return configure(connection, connector, endPoint);
204 }
205
206
207
208
209 @Deprecated
210 protected FlowControlStrategy newFlowControlStrategy()
211 {
212 return null;
213 }
214
215 protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint);
216
217 protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
218 {
219 return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
220 }
221
222 private class ConnectionListener implements Connection.Listener
223 {
224 @Override
225 public void onOpened(Connection connection)
226 {
227 addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
228 }
229
230 @Override
231 public void onClosed(Connection connection)
232 {
233 removeBean(((HTTP2Connection)connection).getSession());
234 }
235 }
236 }