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
39 @ManagedObject
40 public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
41 {
42 private final Connection.Listener connectionListener = new ConnectionListener();
43 private final HttpConfiguration httpConfiguration;
44 private int maxDynamicTableSize = 4096;
45 private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
46 private int maxConcurrentStreams = -1;
47 private int maxHeaderBlockFragment = 0;
48 private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
49
50 public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
51 {
52 this(httpConfiguration,"h2","h2-17","h2-16","h2-15","h2-14");
53 }
54
55 protected AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration, String... protocols)
56 {
57 super(protocols);
58 this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
59 addBean(httpConfiguration);
60 }
61
62 @ManagedAttribute("The HPACK dynamic table maximum size")
63 public int getMaxDynamicTableSize()
64 {
65 return maxDynamicTableSize;
66 }
67
68 public void setMaxDynamicTableSize(int maxDynamicTableSize)
69 {
70 this.maxDynamicTableSize = maxDynamicTableSize;
71 }
72
73 @ManagedAttribute("The initial size of stream's flow control send window")
74 public int getInitialStreamSendWindow()
75 {
76 return initialStreamSendWindow;
77 }
78
79 public void setInitialStreamSendWindow(int initialStreamSendWindow)
80 {
81 this.initialStreamSendWindow = initialStreamSendWindow;
82 }
83
84 @ManagedAttribute("The max number of concurrent streams per session")
85 public int getMaxConcurrentStreams()
86 {
87 return maxConcurrentStreams;
88 }
89
90 public void setMaxConcurrentStreams(int maxConcurrentStreams)
91 {
92 this.maxConcurrentStreams = maxConcurrentStreams;
93 }
94
95 public int getMaxHeaderBlockFragment()
96 {
97 return maxHeaderBlockFragment;
98 }
99
100 public void setMaxHeaderBlockFragment(int maxHeaderBlockFragment)
101 {
102 this.maxHeaderBlockFragment = maxHeaderBlockFragment;
103 }
104
105 public FlowControlStrategy.Factory getFlowControlStrategyFactory()
106 {
107 return flowControlStrategyFactory;
108 }
109
110 public void setFlowControlStrategyFactory(FlowControlStrategy.Factory flowControlStrategyFactory)
111 {
112 this.flowControlStrategyFactory = flowControlStrategyFactory;
113 }
114
115 public HttpConfiguration getHttpConfiguration()
116 {
117 return httpConfiguration;
118 }
119
120 @Override
121 public Connection newConnection(Connector connector, EndPoint endPoint)
122 {
123 ServerSessionListener listener = newSessionListener(connector, endPoint);
124
125 Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
126 FlowControlStrategy flowControl = newFlowControlStrategy();
127 if (flowControl == null)
128 flowControl = getFlowControlStrategyFactory().newFlowControlStrategy();
129 HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl);
130 session.setMaxLocalStreams(getMaxConcurrentStreams());
131 session.setMaxRemoteStreams(getMaxConcurrentStreams());
132
133
134
135
136 session.setStreamIdleTimeout(endPoint.getIdleTimeout());
137
138 ServerParser parser = newServerParser(connector, session);
139 HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
140 endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
141 connection.addListener(connectionListener);
142 return configure(connection, connector, endPoint);
143 }
144
145
146
147
148 @Deprecated
149 protected FlowControlStrategy newFlowControlStrategy()
150 {
151 return null;
152 }
153
154 protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint);
155
156 protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
157 {
158 return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
159 }
160
161 private class ConnectionListener implements Connection.Listener
162 {
163 @Override
164 public void onOpened(Connection connection)
165 {
166 addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
167 }
168
169 @Override
170 public void onClosed(Connection connection)
171 {
172 removeBean(((HTTP2Connection)connection).getSession());
173 }
174 }
175 }