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.server;
20  
21  import java.io.IOException;
22  import java.net.InetSocketAddress;
23  import java.net.ServerSocket;
24  import java.net.Socket;
25  import java.net.SocketException;
26  import java.nio.channels.Channel;
27  import java.nio.channels.SelectionKey;
28  import java.nio.channels.Selector;
29  import java.nio.channels.ServerSocketChannel;
30  import java.nio.channels.SocketChannel;
31  import java.util.concurrent.Executor;
32  import java.util.concurrent.Future;
33  
34  import org.eclipse.jetty.io.ByteBufferPool;
35  import org.eclipse.jetty.io.Connection;
36  import org.eclipse.jetty.io.EndPoint;
37  import org.eclipse.jetty.io.ManagedSelector;
38  import org.eclipse.jetty.io.SelectChannelEndPoint;
39  import org.eclipse.jetty.io.SelectorManager;
40  import org.eclipse.jetty.util.Callback;
41  import org.eclipse.jetty.util.annotation.ManagedAttribute;
42  import org.eclipse.jetty.util.annotation.ManagedObject;
43  import org.eclipse.jetty.util.annotation.Name;
44  import org.eclipse.jetty.util.ssl.SslContextFactory;
45  import org.eclipse.jetty.util.thread.ExecutionStrategy;
46  import org.eclipse.jetty.util.thread.Scheduler;
47  
48  /**
49   * This {@link Connector} implementation is the primary connector for the
50   * Jetty server over TCP/IP.  By the use of various {@link ConnectionFactory} instances it is able
51   * to accept connections for HTTP, HTTP/2 and WebSocket, either directly or over SSL.
52   * <p>
53   * The connector is a fully asynchronous NIO based implementation that by default will
54   * use all the commons services (eg {@link Executor}, {@link Scheduler})  of the
55   * passed {@link Server} instance, but all services may also be constructor injected
56   * into the connector so that it may operate with dedicated or otherwise shared services.
57   * <h2>Connection Factories</h2>
58   * Various convenience constructors are provided to assist with common configurations of
59   * ConnectionFactories, whose generic use is described in {@link AbstractConnector}.
60   * If no connection factories are passed, then the connector will
61   * default to use a {@link HttpConnectionFactory}.  If an non null {@link SslContextFactory}
62   * instance is passed, then this used to instantiate a {@link SslConnectionFactory} which is
63   * prepended to the other passed or default factories.
64   * <h2>Selectors</h2>
65   * The connector will use the {@link Executor} service to execute a number of Selector Tasks,
66   * which are implemented to each use a NIO {@link Selector} instance to asynchronously
67   * schedule a set of accepted connections.  It is the selector thread that will call the
68   * {@link Callback} instances passed in the {@link EndPoint#fillInterested(Callback)} or
69   * {@link EndPoint#write(Callback, java.nio.ByteBuffer...)} methods.  It is expected
70   * that these callbacks may do some non-blocking IO work, but will always dispatch to the
71   * {@link Executor} service any blocking, long running or application tasks.
72   * <p>
73   * The default number of selectors is equal to the number of processors available to the JVM,
74   * which should allow optimal performance even if all the connections used are performing
75   * significant non-blocking work in the callback tasks.
76   */
77  @ManagedObject("HTTP connector using NIO ByteChannels and Selectors")
78  public class ServerConnector extends AbstractNetworkConnector
79  {
80      private final SelectorManager _manager;
81      private volatile ServerSocketChannel _acceptChannel;
82      private volatile boolean _inheritChannel = false;
83      private volatile int _localPort = -1;
84      private volatile int _acceptQueueSize = 0;
85      private volatile boolean _reuseAddress = true;
86      private volatile int _lingerTime = -1;
87  
88      /**
89       * <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the only factory.</p>
90       * @param server The {@link Server} this connector will accept connection for.
91       */
92      public ServerConnector(
93          @Name("server") Server server)
94      {
95          this(server,null,null,null,-1,-1,new HttpConnectionFactory());
96      }
97  
98      /**
99       * <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the only factory.</p>
100      * @param server The {@link Server} this connector will accept connection for.
101      * @param acceptors
102      *          the number of acceptor threads to use, or -1 for a default value. Acceptors accept new TCP/IP connections.  If 0, then
103      *          the selector threads are used to accept connections.
104      * @param selectors
105      *          the number of selector threads, or &lt;=0 for a default value. Selectors notice and schedule established connection that can make IO progress.
106      */
107     public ServerConnector(
108         @Name("server") Server server,
109         @Name("acceptors") int acceptors,
110         @Name("selectors") int selectors)
111     {
112         this(server,null,null,null,acceptors,selectors,new HttpConnectionFactory());
113     }
114 
115     /**
116      * <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the only factory.</p>
117      * @param server The {@link Server} this connector will accept connection for.
118      * @param acceptors
119      *          the number of acceptor threads to use, or -1 for a default value. Acceptors accept new TCP/IP connections.  If 0, then
120      *          the selector threads are used to accept connections.
121      * @param selectors
122      *          the number of selector threads, or &lt;=0 for a default value. Selectors notice and schedule established connection that can make IO progress.
123      * @param factories Zero or more {@link ConnectionFactory} instances used to create and configure connections.
124      */
125     public ServerConnector(
126         @Name("server") Server server,
127         @Name("acceptors") int acceptors,
128         @Name("selectors") int selectors,
129         @Name("factories") ConnectionFactory... factories)
130     {
131         this(server,null,null,null,acceptors,selectors,factories);
132     }
133 
134     /**
135      * <p>Construct a Server Connector with the passed Connection factories.</p>
136      * @param server The {@link Server} this connector will accept connection for.
137      * @param factories Zero or more {@link ConnectionFactory} instances used to create and configure connections.
138      */
139     public ServerConnector(
140         @Name("server") Server server,
141         @Name("factories") ConnectionFactory... factories)
142     {
143         this(server,null,null,null,-1,-1,factories);
144     }
145 
146     /**
147      * <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the primary protocol</p>.
148      * @param server The {@link Server} this connector will accept connection for.
149      * @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
150      * list of HTTP Connection Factory.
151      */
152     public ServerConnector(
153         @Name("server") Server server,
154         @Name("sslContextFactory") SslContextFactory sslContextFactory)
155     {
156         this(server,null,null,null,-1,-1,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
157     }
158 
159     /**
160      * <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the primary protocol</p>.
161      * @param server The {@link Server} this connector will accept connection for.
162      * @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
163      * list of HTTP Connection Factory.
164      * @param acceptors
165      *          the number of acceptor threads to use, or -1 for a default value. Acceptors accept new TCP/IP connections.  If 0, then
166      *          the selector threads are used to accept connections.
167      * @param selectors
168      *          the number of selector threads, or &lt;=0 for a default value. Selectors notice and schedule established connection that can make IO progress.
169      */
170     public ServerConnector(
171         @Name("server") Server server,
172         @Name("acceptors") int acceptors,
173         @Name("selectors") int selectors,
174         @Name("sslContextFactory") SslContextFactory sslContextFactory)
175     {
176         this(server,null,null,null,acceptors,selectors,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
177     }
178 
179     /**
180      * @param server The {@link Server} this connector will accept connection for.
181      * @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
182      * list of ConnectionFactories, with the first factory being the default protocol for the SslConnectionFactory.
183      * @param factories Zero or more {@link ConnectionFactory} instances used to create and configure connections.
184      */
185     public ServerConnector(
186         @Name("server") Server server,
187         @Name("sslContextFactory") SslContextFactory sslContextFactory,
188         @Name("factories") ConnectionFactory... factories)
189     {
190         this(server, null, null, null, -1, -1, AbstractConnectionFactory.getFactories(sslContextFactory, factories));
191     }
192 
193     /**
194      * @param server
195      *          The server this connector will be accept connection for.
196      * @param executor
197      *          An executor used to run tasks for handling requests, acceptors and selectors.
198      *          If null then use the servers executor
199      * @param scheduler
200      *          A scheduler used to schedule timeouts. If null then use the servers scheduler
201      * @param bufferPool
202      *          A ByteBuffer pool used to allocate buffers.  If null then create a private pool with default configuration.
203      * @param acceptors
204      *          the number of acceptor threads to use, or -1 for a default value. Acceptors accept new TCP/IP connections.  If 0, then
205      *          the selector threads are used to accept connections.
206      * @param selectors
207      *          the number of selector threads, or &lt;=0 for a default value. Selectors notice and schedule established connection that can make IO progress.
208      * @param factories
209      *          Zero or more {@link ConnectionFactory} instances used to create and configure connections.
210      */
211     public ServerConnector(
212         @Name("server") Server server,
213         @Name("executor") Executor executor,
214         @Name("scheduler") Scheduler scheduler,
215         @Name("bufferPool") ByteBufferPool bufferPool,
216         @Name("acceptors") int acceptors,
217         @Name("selectors") int selectors,
218         @Name("factories") ConnectionFactory... factories)
219     {
220         super(server,executor,scheduler,bufferPool,acceptors,factories);
221         _manager = newSelectorManager(getExecutor(), getScheduler(),
222             selectors>0?selectors:Math.max(1,Math.min(4,Runtime.getRuntime().availableProcessors()/2)));
223         addBean(_manager, true);
224         setAcceptorPriorityDelta(-2);
225     }
226 
227     protected SelectorManager newSelectorManager(Executor executor, Scheduler scheduler, int selectors)
228     {
229         return new ServerConnectorManager(executor, scheduler, selectors);
230     }
231 
232     @Override
233     protected void doStart() throws Exception
234     {
235         super.doStart();
236 
237         if (getAcceptors()==0)
238         {
239             _acceptChannel.configureBlocking(false);
240             _manager.acceptor(_acceptChannel);
241         }
242     }
243 
244     @Override
245     public boolean isOpen()
246     {
247         ServerSocketChannel channel = _acceptChannel;
248         return channel!=null && channel.isOpen();
249     }
250 
251     /**
252      * @return the selector priority delta
253      * @deprecated not implemented
254      */
255     @Deprecated
256     public int getSelectorPriorityDelta()
257     {
258         return _manager.getSelectorPriorityDelta();
259     }
260 
261     /**
262      * @param selectorPriorityDelta the selector priority delta
263      * @deprecated not implemented
264      */
265     @Deprecated
266     public void setSelectorPriorityDelta(int selectorPriorityDelta)
267     {
268         _manager.setSelectorPriorityDelta(selectorPriorityDelta);
269     }
270 
271     /**
272      * @return whether this connector uses a channel inherited from the JVM.
273      * @see System#inheritedChannel()
274      */
275     public boolean isInheritChannel()
276     {
277         return _inheritChannel;
278     }
279 
280     /**
281      * <p>Sets whether this connector uses a channel inherited from the JVM.</p>
282      * <p>If true, the connector first tries to inherit from a channel provided by the system.
283      * If there is no inherited channel available, or if the inherited channel is not usable,
284      * then it will fall back using {@link ServerSocketChannel}.</p>
285      * <p>Use it with xinetd/inetd, to launch an instance of Jetty on demand. The port
286      * used to access pages on the Jetty instance is the same as the port used to
287      * launch Jetty.</p>
288      *
289      * @param inheritChannel whether this connector uses a channel inherited from the JVM.
290      */
291     public void setInheritChannel(boolean inheritChannel)
292     {
293         _inheritChannel = inheritChannel;
294     }
295 
296     @Override
297     public void open() throws IOException
298     {
299         if (_acceptChannel == null)
300         {
301             ServerSocketChannel serverChannel = null;
302             if (isInheritChannel())
303             {
304                 Channel channel = System.inheritedChannel();
305                 if (channel instanceof ServerSocketChannel)
306                     serverChannel = (ServerSocketChannel)channel;
307                 else
308                     LOG.warn("Unable to use System.inheritedChannel() [{}]. Trying a new ServerSocketChannel at {}:{}", channel, getHost(), getPort());
309             }
310 
311             if (serverChannel == null)
312             {
313                 serverChannel = ServerSocketChannel.open();
314 
315                 InetSocketAddress bindAddress = getHost() == null ? new InetSocketAddress(getPort()) : new InetSocketAddress(getHost(), getPort());
316                 serverChannel.socket().setReuseAddress(getReuseAddress());
317                 serverChannel.socket().bind(bindAddress, getAcceptQueueSize());
318 
319                 _localPort = serverChannel.socket().getLocalPort();
320                 if (_localPort <= 0)
321                     throw new IOException("Server channel not bound");
322 
323                 addBean(serverChannel);
324             }
325 
326             serverChannel.configureBlocking(true);
327             addBean(serverChannel);
328 
329             _acceptChannel = serverChannel;
330         }
331     }
332 
333     @Override
334     public Future<Void> shutdown()
335     {
336         // shutdown all the connections
337         return super.shutdown();
338     }
339 
340     @Override
341     public void close()
342     {
343         ServerSocketChannel serverChannel = _acceptChannel;
344         _acceptChannel = null;
345 
346         if (serverChannel != null)
347         {
348             removeBean(serverChannel);
349 
350             // If the interrupt did not close it, we should close it
351             if (serverChannel.isOpen())
352             {
353                 try
354                 {
355                     serverChannel.close();
356                 }
357                 catch (IOException e)
358                 {
359                     LOG.warn(e);
360                 }
361             }
362         }
363         // super.close();
364         _localPort = -2;
365     }
366 
367     @Override
368     public void accept(int acceptorID) throws IOException
369     {
370         ServerSocketChannel serverChannel = _acceptChannel;
371         if (serverChannel != null && serverChannel.isOpen())
372         {
373             SocketChannel channel = serverChannel.accept();
374             accepted(channel);
375         }
376     }
377 
378     private void accepted(SocketChannel channel) throws IOException
379     {
380         channel.configureBlocking(false);
381         Socket socket = channel.socket();
382         configure(socket);
383         _manager.accept(channel);
384     }
385 
386     protected void configure(Socket socket)
387     {
388         try
389         {
390             socket.setTcpNoDelay(true);
391             if (_lingerTime >= 0)
392                 socket.setSoLinger(true, _lingerTime / 1000);
393             else
394                 socket.setSoLinger(false, 0);
395         }
396         catch (SocketException e)
397         {
398             LOG.ignore(e);
399         }
400     }
401 
402     public SelectorManager getSelectorManager()
403     {
404         return _manager;
405     }
406 
407     @Override
408     public Object getTransport()
409     {
410         return _acceptChannel;
411     }
412 
413     @Override
414     @ManagedAttribute("local port")
415     public int getLocalPort()
416     {
417         return _localPort;
418     }
419 
420     protected SelectChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey key) throws IOException
421     {
422         return new SelectChannelEndPoint(channel, selectSet, key, getScheduler(), getIdleTimeout());
423     }
424 
425     /**
426      * @return the linger time
427      * @see Socket#getSoLinger()
428      */
429     @ManagedAttribute("TCP/IP solinger time or -1 to disable")
430     public int getSoLingerTime()
431     {
432         return _lingerTime;
433     }
434 
435     /**
436      * @param lingerTime the linger time. Use -1 to disable.
437      * @see Socket#setSoLinger(boolean, int)
438      */
439     public void setSoLingerTime(int lingerTime)
440     {
441         _lingerTime = lingerTime;
442     }
443 
444     /**
445      * @return the accept queue size
446      */
447     @ManagedAttribute("Accept Queue size")
448     public int getAcceptQueueSize()
449     {
450         return _acceptQueueSize;
451     }
452 
453     /**
454      * @param acceptQueueSize the accept queue size (also known as accept backlog)
455      */
456     public void setAcceptQueueSize(int acceptQueueSize)
457     {
458         _acceptQueueSize = acceptQueueSize;
459     }
460 
461     /**
462      * @return whether the server socket reuses addresses
463      * @see ServerSocket#getReuseAddress()
464      */
465     public boolean getReuseAddress()
466     {
467         return _reuseAddress;
468     }
469 
470     /**
471      * @param reuseAddress whether the server socket reuses addresses
472      * @see ServerSocket#setReuseAddress(boolean)
473      */
474     public void setReuseAddress(boolean reuseAddress)
475     {
476         _reuseAddress = reuseAddress;
477     }
478 
479     /**
480      * @return the ExecutionStrategy factory to use for SelectorManager
481      */
482     public ExecutionStrategy.Factory getExecutionStrategyFactory()
483     {
484         return _manager.getExecutionStrategyFactory();
485     }
486 
487     /**
488      * @param executionFactory the ExecutionStrategy factory to use for SelectorManager
489      */
490     public void setExecutionStrategyFactory(ExecutionStrategy.Factory executionFactory)
491     {
492         _manager.setExecutionStrategyFactory(executionFactory);
493     }
494 
495     protected class ServerConnectorManager extends SelectorManager
496     {
497         public ServerConnectorManager(Executor executor, Scheduler scheduler, int selectors)
498         {
499             super(executor, scheduler, selectors);
500         }
501 
502         @Override
503         protected void accepted(SocketChannel channel) throws IOException
504         {
505             ServerConnector.this.accepted(channel);
506         }
507 
508         @Override
509         protected SelectChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey selectionKey) throws IOException
510         {
511             return ServerConnector.this.newEndPoint(channel, selectSet, selectionKey);
512         }
513 
514         @Override
515         public Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment) throws IOException
516         {
517             return getDefaultConnectionFactory().newConnection(ServerConnector.this, endpoint);
518         }
519 
520         @Override
521         protected void endPointOpened(EndPoint endpoint)
522         {
523             super.endPointOpened(endpoint);
524             onEndPointOpened(endpoint);
525         }
526 
527         @Override
528         protected void endPointClosed(EndPoint endpoint)
529         {
530             onEndPointClosed(endpoint);
531             super.endPointClosed(endpoint);
532         }
533     }
534 }