View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.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         // For a single stream in a connection, there will be a race between
133         // the stream idle timeout and the connection idle timeout. However,
134         // the typical case is that the connection will be busier and the
135         // stream idle timeout will expire earlier that the connection's.
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      * @deprecated use {@link #setFlowControlStrategyFactory(FlowControlStrategy.Factory)} instead
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 }