View Javadoc

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