View Javadoc

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