Mercurial Hosting > luan
changeset 885:150092cebf3e
remove AbstractConnector
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 04 Oct 2016 20:11:48 -0600 |
parents | cb78ee27b0e0 |
children | 0d876a03ab0b |
files | src/org/eclipse/jetty/server/AbstractConnector.java src/org/eclipse/jetty/server/AbstractHttpConnection.java src/org/eclipse/jetty/server/Connector.java src/org/eclipse/jetty/server/nio/AbstractNIOConnector.java src/org/eclipse/jetty/server/ssl/SslConnector.java src/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java |
diffstat | 6 files changed, 950 insertions(+), 1580 deletions(-) [+] |
line wrap: on
line diff
--- a/src/org/eclipse/jetty/server/AbstractConnector.java Tue Oct 04 16:30:02 2016 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1025 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.server; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicLong; - -import javax.servlet.ServletRequest; - -import org.eclipse.jetty.http.HttpBuffers; -import org.eclipse.jetty.http.HttpBuffersImpl; -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeaders; -import org.eclipse.jetty.http.HttpSchemes; -import org.eclipse.jetty.io.Buffers; -import org.eclipse.jetty.io.Buffers.Type; -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.util.component.AggregateLifeCycle; -import org.eclipse.jetty.util.component.Dumpable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstract Connector implementation. This abstract implementation of the Connector interface provides: - * <ul> - * <li>AbstractLifeCycle implementation</li> - * <li>Implementations for connector getters and setters</li> - * <li>Buffer management</li> - * <li>Socket configuration</li> - * <li>Base acceptor thread</li> - * <li>Optional reverse proxy headers checking</li> - * </ul> - */ -public abstract class AbstractConnector extends AggregateLifeCycle implements HttpBuffers, Connector, Dumpable -{ - private static final Logger LOG = LoggerFactory.getLogger(AbstractConnector.class); - - private String _name; - - private Server _server; - private String _host; - private int _port = 0; - private String _integralScheme = HttpSchemes.HTTPS; - private int _integralPort = 0; - private String _confidentialScheme = HttpSchemes.HTTPS; - private int _confidentialPort = 0; - private int _acceptQueueSize = 0; - private int _acceptors = 1; - private int _acceptorPriorityOffset = 0; - private boolean _useDNS; - private boolean _forwarded; - private String _hostHeader; - - private String _forwardedHostHeader = HttpHeaders.X_FORWARDED_HOST; - private String _forwardedServerHeader = HttpHeaders.X_FORWARDED_SERVER; - private String _forwardedForHeader = HttpHeaders.X_FORWARDED_FOR; - private String _forwardedProtoHeader = HttpHeaders.X_FORWARDED_PROTO; - private String _forwardedCipherSuiteHeader; - private String _forwardedSslSessionIdHeader; - private boolean _reuseAddress = true; - - protected int _maxIdleTime = 200000; - protected int _lowResourceMaxIdleTime = -1; - protected int _soLingerTime = -1; - - private transient Thread[] _acceptorThreads; - - protected final HttpBuffersImpl _buffers = new HttpBuffersImpl(); - - /* ------------------------------------------------------------ */ - /** - */ - public AbstractConnector() - { - addBean(_buffers); - } - - /* ------------------------------------------------------------ */ - /* - */ - public Server getServer() - { - return _server; - } - - /* ------------------------------------------------------------ */ - public void setServer(Server server) - { - _server = server; - } - - /* ------------------------------------------------------------ */ - public ThreadPoolExecutor getThreadPool() - { - return _server.threadPool; - } - - /* ------------------------------------------------------------ */ - /** - */ - public void setHost(String host) - { - _host = host; - } - - /* ------------------------------------------------------------ */ - /* - */ - public String getHost() - { - return _host; - } - - /* ------------------------------------------------------------ */ - public void setPort(int port) - { - _port = port; - } - - /* ------------------------------------------------------------ */ - public int getPort() - { - return _port; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the maxIdleTime. - */ - public int getMaxIdleTime() - { - return _maxIdleTime; - } - - /* ------------------------------------------------------------ */ - /** - * Set the maximum Idle time for a connection, which roughly translates to the {@link Socket#setSoTimeout(int)} call, although with NIO implementations - * other mechanisms may be used to implement the timeout. The max idle time is applied: - * <ul> - * <li>When waiting for a new request to be received on a connection</li> - * <li>When reading the headers and content of a request</li> - * <li>When writing the headers and content of a response</li> - * </ul> - * Jetty interprets this value as the maximum time between some progress being made on the connection. So if a single byte is read or written, then the - * timeout (if implemented by jetty) is reset. However, in many instances, the reading/writing is delegated to the JVM, and the semantic is more strictly - * enforced as the maximum time a single read/write operation can take. Note, that as Jetty supports writes of memory mapped file buffers, then a write may - * take many 10s of seconds for large content written to a slow device. - * <p> - * Previously, Jetty supported separate idle timeouts and IO operation timeouts, however the expense of changing the value of soTimeout was significant, so - * these timeouts were merged. With the advent of NIO, it may be possible to again differentiate these values (if there is demand). - * - * @param maxIdleTime - * The maxIdleTime to set. - */ - public void setMaxIdleTime(int maxIdleTime) - { - _maxIdleTime = maxIdleTime; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the maxIdleTime when resources are low. - */ - public int getLowResourcesMaxIdleTime() - { - return _lowResourceMaxIdleTime; - } - - /* ------------------------------------------------------------ */ - /** - * @param maxIdleTime - * The maxIdleTime to set when resources are low. - */ - public void setLowResourcesMaxIdleTime(int maxIdleTime) - { - _lowResourceMaxIdleTime = maxIdleTime; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the maxIdleTime when resources are low. - * @deprecated - */ - @Deprecated - public final int getLowResourceMaxIdleTime() - { - return getLowResourcesMaxIdleTime(); - } - - /* ------------------------------------------------------------ */ - /** - * @param maxIdleTime - * The maxIdleTime to set when resources are low. - * @deprecated - */ - @Deprecated - public final void setLowResourceMaxIdleTime(int maxIdleTime) - { - setLowResourcesMaxIdleTime(maxIdleTime); - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the soLingerTime. - */ - public int getSoLingerTime() - { - return _soLingerTime; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the acceptQueueSize. - */ - public int getAcceptQueueSize() - { - return _acceptQueueSize; - } - - /* ------------------------------------------------------------ */ - /** - * @param acceptQueueSize - * The acceptQueueSize to set. - */ - public void setAcceptQueueSize(int acceptQueueSize) - { - _acceptQueueSize = acceptQueueSize; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the number of acceptor threads. - */ - public int getAcceptors() - { - return _acceptors; - } - - /* ------------------------------------------------------------ */ - /** - * @param acceptors - * The number of acceptor threads to set. - */ - public void setAcceptors(int acceptors) - { - if (acceptors > 2 * Runtime.getRuntime().availableProcessors()) - LOG.warn("Acceptors should be <=2*availableProcessors: " + this); - _acceptors = acceptors; - } - - /* ------------------------------------------------------------ */ - /** - * @param soLingerTime - * The soLingerTime to set or -1 to disable. - */ - public void setSoLingerTime(int soLingerTime) - { - _soLingerTime = soLingerTime; - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStart() throws Exception - { - if (_server == null) - throw new IllegalStateException("No server"); - - // open listener port - open(); - - super.doStart(); - - // Start selector thread - synchronized (this) - { - _acceptorThreads = new Thread[getAcceptors()]; - - ThreadPoolExecutor _threadPool = getThreadPool(); - for (int i = 0; i < _acceptorThreads.length; i++) - _threadPool.execute(new Acceptor(i)); - if (_server.isLowOnThreads()) - LOG.warn("insufficient threads configured for {}",this); - } - - LOG.info("Started {}",this); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStop() throws Exception - { - try - { - close(); - } - catch (IOException e) - { - LOG.warn("",e); - } - - super.doStop(); - - Thread[] acceptors; - synchronized (this) - { - acceptors = _acceptorThreads; - _acceptorThreads = null; - } - if (acceptors != null) - { - for (Thread thread : acceptors) - { - if (thread != null) - thread.interrupt(); - } - } - } - - /* ------------------------------------------------------------ */ - public void join() throws InterruptedException - { - Thread[] threads; - synchronized(this) - { - threads=_acceptorThreads; - } - if (threads != null) - for (Thread thread : threads) - if (thread != null) - thread.join(); - } - - /* ------------------------------------------------------------ */ - protected void configure(Socket socket) throws IOException - { - try - { - socket.setTcpNoDelay(true); - if (_soLingerTime >= 0) - socket.setSoLinger(true,_soLingerTime / 1000); - else - socket.setSoLinger(false,0); - } - catch (Exception e) - { - LOG.trace("",e); - } - } - - /* ------------------------------------------------------------ */ - public void customize(EndPoint endpoint, Request request) throws IOException - { - if (isForwarded()) - checkForwardedHeaders(endpoint,request); - } - - /* ------------------------------------------------------------ */ - protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException - { - HttpFields httpFields = request.getConnection().getRequestFields(); - - // Do SSL first - if (getForwardedCipherSuiteHeader()!=null) - { - String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); - if (cipher_suite!=null) - request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); - } - if (getForwardedSslSessionIdHeader()!=null) - { - String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); - if(ssl_session_id!=null) - { - request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); - request.setScheme(HttpSchemes.HTTPS); - } - } - - // Retrieving headers from the request - String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); - String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); - String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); - String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); - - if (_hostHeader != null) - { - // Update host header - httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader); - request.setServerName(null); - request.setServerPort(-1); - request.getServerName(); - } - else if (forwardedHost != null) - { - // Update host header - httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost); - request.setServerName(null); - request.setServerPort(-1); - request.getServerName(); - } - else if (forwardedServer != null) - { - // Use provided server name - request.setServerName(forwardedServer); - } - - if (forwardedFor != null) - { - request.setRemoteAddr(forwardedFor); - InetAddress inetAddress = null; - - if (_useDNS) - { - try - { - inetAddress = InetAddress.getByName(forwardedFor); - } - catch (UnknownHostException e) - { - LOG.trace("",e); - } - } - - request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName()); - } - - if (forwardedProto != null) - { - request.setScheme(forwardedProto); - } - } - - /* ------------------------------------------------------------ */ - protected String getLeftMostFieldValue(HttpFields fields, String header) - { - if (header == null) - return null; - - String headerValue = fields.getStringField(header); - - if (headerValue == null) - return null; - - int commaIndex = headerValue.indexOf(','); - - if (commaIndex == -1) - { - // Single value - return headerValue; - } - - // The left-most value is the farthest downstream client - return headerValue.substring(0,commaIndex); - } - - /* ------------------------------------------------------------ */ - public void persist(EndPoint endpoint) throws IOException - { - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialPort() - */ - public int getConfidentialPort() - { - return _confidentialPort; - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialScheme() - */ - public String getConfidentialScheme() - { - return _confidentialScheme; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server .Request) - */ - public boolean isIntegral(Request request) - { - return false; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getConfidentialPort() - */ - public int getIntegralPort() - { - return _integralPort; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#getIntegralScheme() - */ - public String getIntegralScheme() - { - return _integralScheme; - } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server.Request) - */ - public boolean isConfidential(Request request) - { - return _forwarded && request.getScheme().equalsIgnoreCase(HttpSchemes.HTTPS); - } - - /* ------------------------------------------------------------ */ - /** - * @param confidentialPort - * The confidentialPort to set. - */ - public void setConfidentialPort(int confidentialPort) - { - _confidentialPort = confidentialPort; - } - - /* ------------------------------------------------------------ */ - /** - * @param confidentialScheme - * The confidentialScheme to set. - */ - public void setConfidentialScheme(String confidentialScheme) - { - _confidentialScheme = confidentialScheme; - } - - /* ------------------------------------------------------------ */ - /** - * @param integralPort - * The integralPort to set. - */ - public void setIntegralPort(int integralPort) - { - _integralPort = integralPort; - } - - /* ------------------------------------------------------------ */ - /** - * @param integralScheme - * The integralScheme to set. - */ - public void setIntegralScheme(String integralScheme) - { - _integralScheme = integralScheme; - } - - /* ------------------------------------------------------------ */ - protected abstract void accept(int acceptorID) throws IOException, InterruptedException; - - /* ------------------------------------------------------------ */ - public void stopAccept(int acceptorID) throws Exception - { - } - - /* ------------------------------------------------------------ */ - public boolean getResolveNames() - { - return _useDNS; - } - - /* ------------------------------------------------------------ */ - public void setResolveNames(boolean resolve) - { - _useDNS = resolve; - } - - /* ------------------------------------------------------------ */ - /** - * Is reverse proxy handling on? - * - * @return true if this connector is checking the x-forwarded-for/host/server headers - */ - public boolean isForwarded() - { - return _forwarded; - } - - /* ------------------------------------------------------------ */ - /** - * Set reverse proxy handling. If set to true, then the X-Forwarded headers (or the headers set in their place) are looked for to set the request protocol, - * host, server and client ip. - * - * @param check - * true if this connector is checking the x-forwarded-for/host/server headers - * @see #setForwardedForHeader(String) - * @see #setForwardedHostHeader(String) - * @see #setForwardedProtoHeader(String) - * @see #setForwardedServerHeader(String) - */ - public void setForwarded(boolean check) - { - if (check) - LOG.debug("{} is forwarded",this); - _forwarded = check; - } - - /* ------------------------------------------------------------ */ - public String getHostHeader() - { - return _hostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. - * This value is only used if {@link #isForwarded()} is true. - * - * @param hostHeader - * The value of the host header to force. - */ - public void setHostHeader(String hostHeader) - { - _hostHeader = hostHeader; - } - - /* ------------------------------------------------------------ */ - /* - * - * @see #setForwarded(boolean) - */ - public String getForwardedHostHeader() - { - return _forwardedHostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedHostHeader - * The header name for forwarded hosts (default x-forwarded-host) - * @see #setForwarded(boolean) - */ - public void setForwardedHostHeader(String forwardedHostHeader) - { - _forwardedHostHeader = forwardedHostHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @return the header name for forwarded server. - * @see #setForwarded(boolean) - */ - public String getForwardedServerHeader() - { - return _forwardedServerHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedServerHeader - * The header name for forwarded server (default x-forwarded-server) - * @see #setForwarded(boolean) - */ - public void setForwardedServerHeader(String forwardedServerHeader) - { - _forwardedServerHeader = forwardedServerHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @see #setForwarded(boolean) - */ - public String getForwardedForHeader() - { - return _forwardedForHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedRemoteAddressHeader - * The header name for forwarded for (default x-forwarded-for) - * @see #setForwarded(boolean) - */ - public void setForwardedForHeader(String forwardedRemoteAddressHeader) - { - _forwardedForHeader = forwardedRemoteAddressHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Get the forwardedProtoHeader. - * - * @return the forwardedProtoHeader (default X-Forwarded-For) - * @see #setForwarded(boolean) - */ - public String getForwardedProtoHeader() - { - return _forwardedProtoHeader; - } - - /* ------------------------------------------------------------ */ - /** - * Set the forwardedProtoHeader. - * - * @param forwardedProtoHeader - * the forwardedProtoHeader to set (default X-Forwarded-For) - * @see #setForwarded(boolean) - */ - public void setForwardedProtoHeader(String forwardedProtoHeader) - { - _forwardedProtoHeader = forwardedProtoHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @return The header name holding a forwarded cipher suite (default null) - */ - public String getForwardedCipherSuiteHeader() - { - return _forwardedCipherSuiteHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedCipherSuite - * The header name holding a forwarded cipher suite (default null) - */ - public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) - { - _forwardedCipherSuiteHeader = forwardedCipherSuite; - } - - /* ------------------------------------------------------------ */ - /** - * @return The header name holding a forwarded SSL Session ID (default null) - */ - public String getForwardedSslSessionIdHeader() - { - return _forwardedSslSessionIdHeader; - } - - /* ------------------------------------------------------------ */ - /** - * @param forwardedSslSessionId - * The header name holding a forwarded SSL Session ID (default null) - */ - public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) - { - _forwardedSslSessionIdHeader = forwardedSslSessionId; - } - - public int getRequestBufferSize() - { - return _buffers.getRequestBufferSize(); - } - - public void setRequestBufferSize(int requestBufferSize) - { - _buffers.setRequestBufferSize(requestBufferSize); - } - - public int getRequestHeaderSize() - { - return _buffers.getRequestHeaderSize(); - } - - public void setRequestHeaderSize(int requestHeaderSize) - { - _buffers.setRequestHeaderSize(requestHeaderSize); - } - - public int getResponseBufferSize() - { - return _buffers.getResponseBufferSize(); - } - - public void setResponseBufferSize(int responseBufferSize) - { - _buffers.setResponseBufferSize(responseBufferSize); - } - - public int getResponseHeaderSize() - { - return _buffers.getResponseHeaderSize(); - } - - public void setResponseHeaderSize(int responseHeaderSize) - { - _buffers.setResponseHeaderSize(responseHeaderSize); - } - - public Type getRequestBufferType() - { - return _buffers.getRequestBufferType(); - } - - public Type getRequestHeaderType() - { - return _buffers.getRequestHeaderType(); - } - - public Type getResponseBufferType() - { - return _buffers.getResponseBufferType(); - } - - public Type getResponseHeaderType() - { - return _buffers.getResponseHeaderType(); - } - - public void setRequestBuffers(Buffers requestBuffers) - { - _buffers.setRequestBuffers(requestBuffers); - } - - public void setResponseBuffers(Buffers responseBuffers) - { - _buffers.setResponseBuffers(responseBuffers); - } - - public Buffers getRequestBuffers() - { - return _buffers.getRequestBuffers(); - } - - public Buffers getResponseBuffers() - { - return _buffers.getResponseBuffers(); - } - - public int getMaxBuffers() - { - return _buffers.getMaxBuffers(); - } - - /* ------------------------------------------------------------ */ - @Override - public String toString() - { - return String.format("%s@%s:%d", - getClass().getSimpleName(), - getHost()==null?"0.0.0.0":getHost(), - getLocalPort()<=0?getPort():getLocalPort()); - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - private class Acceptor implements Runnable - { - int _acceptor = 0; - - Acceptor(int id) - { - _acceptor = id; - } - - /* ------------------------------------------------------------ */ - public void run() - { - Thread current = Thread.currentThread(); - String name; - synchronized (AbstractConnector.this) - { - if (_acceptorThreads == null) - return; - - _acceptorThreads[_acceptor] = current; - name = _acceptorThreads[_acceptor].getName(); - current.setName(name + " Acceptor" + _acceptor + " " + AbstractConnector.this); - } - int old_priority = current.getPriority(); - - try - { - current.setPriority(old_priority - _acceptorPriorityOffset); - while (isRunning() && getConnection() != null) - { - try - { - accept(_acceptor); - } - catch (EofException e) - { - LOG.trace("",e); - } - catch (IOException e) - { - LOG.trace("",e); - } - catch (InterruptedException x) - { - // Connector has been stopped - LOG.trace("",x); - } - catch (Throwable e) - { - LOG.warn("",e); - } - } - } - finally - { - current.setPriority(old_priority); - current.setName(name); - - synchronized (AbstractConnector.this) - { - if (_acceptorThreads != null) - _acceptorThreads[_acceptor] = null; - } - } - } - } - - /* ------------------------------------------------------------ */ - public String getName() - { - if (_name == null) - _name = (getHost() == null?"0.0.0.0":getHost()) + ":" + (getLocalPort() <= 0?getPort():getLocalPort()); - return _name; - } - - /* ------------------------------------------------------------ */ - public void setName(String name) - { - _name = name; - } - - /* ------------------------------------------------------------ */ - protected void connectionOpened(Connection connection) - { - } - - /* ------------------------------------------------------------ */ - protected void connectionUpgraded(Connection oldConnection, Connection newConnection) - { - } - - /* ------------------------------------------------------------ */ - protected void connectionClosed(Connection connection) - { - connection.onClose(); - } - - /* ------------------------------------------------------------ */ - /** - * @return the acceptorPriority - */ - public int getAcceptorPriorityOffset() - { - return _acceptorPriorityOffset; - } - - /* ------------------------------------------------------------ */ - /** - * Set the priority offset of the acceptor threads. The priority is adjusted by this amount (default 0) to either favour the acceptance of new threads and - * newly active connections or to favour the handling of already dispatched connections. - * - * @param offset - * the amount to alter the priority of the acceptor threads. - */ - public void setAcceptorPriorityOffset(int offset) - { - _acceptorPriorityOffset = offset; - } - - /* ------------------------------------------------------------ */ - /** - * @return True if the the server socket will be opened in SO_REUSEADDR mode. - */ - public boolean getReuseAddress() - { - return _reuseAddress; - } - - /* ------------------------------------------------------------ */ - /** - * @param reuseAddress - * True if the the server socket will be opened in SO_REUSEADDR mode. - */ - public void setReuseAddress(boolean reuseAddress) - { - _reuseAddress = reuseAddress; - } - - /* ------------------------------------------------------------ */ - public final boolean isLowResources() - { - return _server.isLowOnThreads(); - } - - /* ------------------------------------------------------------ */ - private void updateNotEqual(AtomicLong valueHolder, long compare, long value) - { - long oldValue = valueHolder.get(); - while (compare != oldValue) - { - if (valueHolder.compareAndSet(oldValue,value)) - break; - oldValue = valueHolder.get(); - } - } -}
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java Tue Oct 04 16:30:02 2016 -0600 +++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java Tue Oct 04 20:11:48 2016 -0600 @@ -55,7 +55,6 @@ import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.nio.NIOConnector; -import org.eclipse.jetty.server.ssl.SslConnector; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil;
--- a/src/org/eclipse/jetty/server/Connector.java Tue Oct 04 16:30:02 2016 -0600 +++ b/src/org/eclipse/jetty/server/Connector.java Tue Oct 04 20:11:48 2016 -0600 @@ -19,269 +19,1013 @@ package org.eclipse.jetty.server; import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicLong; -import org.eclipse.jetty.io.Buffers; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.util.component.LifeCycle; +import javax.servlet.ServletRequest; -/** HTTP Connector. - * Implementations of this interface provide connectors for the HTTP protocol. - * A connector receives requests (normally from a socket) and calls the - * handle method of the Handler object. These operations are performed using - * threads from the ThreadPool set on the connector. - * - * When a connector is registered with an instance of Server, then the server - * will set itself as both the ThreadPool and the Handler. Note that a connector - * can be used without a Server if a thread pool and handler are directly provided. - * - * - * - */ +import org.eclipse.jetty.http.HttpBuffers; +import org.eclipse.jetty.http.HttpBuffersImpl; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeaders; +import org.eclipse.jetty.http.HttpSchemes; +import org.eclipse.jetty.io.Buffers; +import org.eclipse.jetty.io.Buffers.Type; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.EofException; +import org.eclipse.jetty.util.component.AggregateLifeCycle; +import org.eclipse.jetty.util.component.Dumpable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * @author gregw - * + * Abstract Connector implementation. This abstract implementation of the Connector interface provides: + * <ul> + * <li>AbstractLifeCycle implementation</li> + * <li>Implementations for connector getters and setters</li> + * <li>Buffer management</li> + * <li>Socket configuration</li> + * <li>Base acceptor thread</li> + * <li>Optional reverse proxy headers checking</li> + * </ul> */ -public interface Connector extends LifeCycle -{ - /* ------------------------------------------------------------ */ - /** - * @return the name of the connector. Defaults to the HostName:port - */ - String getName(); - - /* ------------------------------------------------------------ */ - /** - * Opens the connector - * @throws IOException - */ - void open() throws IOException; +public abstract class Connector extends AggregateLifeCycle implements HttpBuffers, Dumpable +{ + private static final Logger LOG = LoggerFactory.getLogger(Connector.class); + + private String _name; - /* ------------------------------------------------------------ */ - void close() throws IOException; + private Server _server; + private String _host; + private int _port = 0; + private String _integralScheme = HttpSchemes.HTTPS; + private int _integralPort = 0; + private String _confidentialScheme = HttpSchemes.HTTPS; + private int _confidentialPort = 0; + private int _acceptQueueSize = 0; + private int _acceptors = 1; + private int _acceptorPriorityOffset = 0; + private boolean _useDNS; + private boolean _forwarded; + private String _hostHeader; - /* ------------------------------------------------------------ */ - void setServer(Server server); - - /* ------------------------------------------------------------ */ - Server getServer(); + private String _forwardedHostHeader = HttpHeaders.X_FORWARDED_HOST; + private String _forwardedServerHeader = HttpHeaders.X_FORWARDED_SERVER; + private String _forwardedForHeader = HttpHeaders.X_FORWARDED_FOR; + private String _forwardedProtoHeader = HttpHeaders.X_FORWARDED_PROTO; + private String _forwardedCipherSuiteHeader; + private String _forwardedSslSessionIdHeader; + private boolean _reuseAddress = true; + + protected int _maxIdleTime = 200000; + protected int _lowResourceMaxIdleTime = -1; + protected int _soLingerTime = -1; + + private transient Thread[] _acceptorThreads; + + protected final HttpBuffersImpl _buffers = new HttpBuffersImpl(); /* ------------------------------------------------------------ */ /** - * @return Returns the request header buffer size in bytes. */ - int getRequestHeaderSize(); - + public Connector() + { + addBean(_buffers); + } + /* ------------------------------------------------------------ */ - /** - * Set the size of the buffer to be used for request headers. - * @param size The size in bytes. + /* */ - void setRequestHeaderSize(int size); + public Server getServer() + { + return _server; + } + + /* ------------------------------------------------------------ */ + public void setServer(Server server) + { + _server = server; + } + + /* ------------------------------------------------------------ */ + public ThreadPoolExecutor getThreadPool() + { + return _server.threadPool; + } /* ------------------------------------------------------------ */ /** - * @return Returns the response header buffer size in bytes. */ - int getResponseHeaderSize(); - + public void setHost(String host) + { + _host = host; + } + /* ------------------------------------------------------------ */ - /** - * Set the size of the buffer to be used for request headers. - * @param size The size in bytes. + /* */ - void setResponseHeaderSize(int size); - + public String getHost() + { + return _host; + } + + /* ------------------------------------------------------------ */ + public void setPort(int port) + { + _port = port; + } + + /* ------------------------------------------------------------ */ + public int getPort() + { + return _port; + } /* ------------------------------------------------------------ */ /** - * @return factory for request buffers + * @return Returns the maxIdleTime. */ - Buffers getRequestBuffers(); + public int getMaxIdleTime() + { + return _maxIdleTime; + } + + /* ------------------------------------------------------------ */ + /** + * Set the maximum Idle time for a connection, which roughly translates to the {@link Socket#setSoTimeout(int)} call, although with NIO implementations + * other mechanisms may be used to implement the timeout. The max idle time is applied: + * <ul> + * <li>When waiting for a new request to be received on a connection</li> + * <li>When reading the headers and content of a request</li> + * <li>When writing the headers and content of a response</li> + * </ul> + * Jetty interprets this value as the maximum time between some progress being made on the connection. So if a single byte is read or written, then the + * timeout (if implemented by jetty) is reset. However, in many instances, the reading/writing is delegated to the JVM, and the semantic is more strictly + * enforced as the maximum time a single read/write operation can take. Note, that as Jetty supports writes of memory mapped file buffers, then a write may + * take many 10s of seconds for large content written to a slow device. + * <p> + * Previously, Jetty supported separate idle timeouts and IO operation timeouts, however the expense of changing the value of soTimeout was significant, so + * these timeouts were merged. With the advent of NIO, it may be possible to again differentiate these values (if there is demand). + * + * @param maxIdleTime + * The maxIdleTime to set. + */ + public void setMaxIdleTime(int maxIdleTime) + { + _maxIdleTime = maxIdleTime; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the maxIdleTime when resources are low. + */ + public int getLowResourcesMaxIdleTime() + { + return _lowResourceMaxIdleTime; + } /* ------------------------------------------------------------ */ /** - * @return factory for response buffers + * @param maxIdleTime + * The maxIdleTime to set when resources are low. */ - Buffers getResponseBuffers(); - - - /* ------------------------------------------------------------ */ - /** - * @return Returns the requestBufferSize. - */ - int getRequestBufferSize(); - + public void setLowResourcesMaxIdleTime(int maxIdleTime) + { + _lowResourceMaxIdleTime = maxIdleTime; + } + /* ------------------------------------------------------------ */ /** - * Set the size of the content buffer for receiving requests. - * These buffers are only used for active connections that have - * requests with bodies that will not fit within the header buffer. - * @param requestBufferSize The requestBufferSize to set. + * @return Returns the maxIdleTime when resources are low. + * @deprecated */ - void setRequestBufferSize(int requestBufferSize); - + @Deprecated + public final int getLowResourceMaxIdleTime() + { + return getLowResourcesMaxIdleTime(); + } + /* ------------------------------------------------------------ */ /** - * @return Returns the responseBufferSize. + * @param maxIdleTime + * The maxIdleTime to set when resources are low. + * @deprecated */ - int getResponseBufferSize(); - - /* ------------------------------------------------------------ */ - /** - * Set the size of the content buffer for sending responses. - * These buffers are only used for active connections that are sending - * responses with bodies that will not fit within the header buffer. - * @param responseBufferSize The responseBufferSize to set. - */ - void setResponseBufferSize(int responseBufferSize); - + @Deprecated + public final void setLowResourceMaxIdleTime(int maxIdleTime) + { + setLowResourcesMaxIdleTime(maxIdleTime); + } /* ------------------------------------------------------------ */ /** - * @return The port to use when redirecting a request if a data constraint of integral is - * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} + * @return Returns the soLingerTime. */ - int getIntegralPort(); + public int getSoLingerTime() + { + return _soLingerTime; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the acceptQueueSize. + */ + public int getAcceptQueueSize() + { + return _acceptQueueSize; + } /* ------------------------------------------------------------ */ /** - * @return The schema to use when redirecting a request if a data constraint of integral is - * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} + * @param acceptQueueSize + * The acceptQueueSize to set. + */ + public void setAcceptQueueSize(int acceptQueueSize) + { + _acceptQueueSize = acceptQueueSize; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the number of acceptor threads. */ - String getIntegralScheme(); + public int getAcceptors() + { + return _acceptors; + } + + /* ------------------------------------------------------------ */ + /** + * @param acceptors + * The number of acceptor threads to set. + */ + public void setAcceptors(int acceptors) + { + if (acceptors > 2 * Runtime.getRuntime().availableProcessors()) + LOG.warn("Acceptors should be <=2*availableProcessors: " + this); + _acceptors = acceptors; + } /* ------------------------------------------------------------ */ /** - * @param request A request - * @return true if the request is integral. This normally means the https schema has been used. + * @param soLingerTime + * The soLingerTime to set or -1 to disable. */ - boolean isIntegral(Request request); + public void setSoLingerTime(int soLingerTime) + { + _soLingerTime = soLingerTime; + } + + /* ------------------------------------------------------------ */ + @Override + protected void doStart() throws Exception + { + if (_server == null) + throw new IllegalStateException("No server"); + + // open listener port + open(); + + super.doStart(); + + // Start selector thread + synchronized (this) + { + _acceptorThreads = new Thread[getAcceptors()]; + + ThreadPoolExecutor _threadPool = getThreadPool(); + for (int i = 0; i < _acceptorThreads.length; i++) + _threadPool.execute(new Acceptor(i)); + if (_server.isLowOnThreads()) + LOG.warn("insufficient threads configured for {}",this); + } + + LOG.info("Started {}",this); + } + + /* ------------------------------------------------------------ */ + @Override + protected void doStop() throws Exception + { + try + { + close(); + } + catch (IOException e) + { + LOG.warn("",e); + } + + super.doStop(); + + Thread[] acceptors; + synchronized (this) + { + acceptors = _acceptorThreads; + _acceptorThreads = null; + } + if (acceptors != null) + { + for (Thread thread : acceptors) + { + if (thread != null) + thread.interrupt(); + } + } + } + + /* ------------------------------------------------------------ */ + public void join() throws InterruptedException + { + Thread[] threads; + synchronized(this) + { + threads=_acceptorThreads; + } + if (threads != null) + for (Thread thread : threads) + if (thread != null) + thread.join(); + } + + /* ------------------------------------------------------------ */ + protected void configure(Socket socket) throws IOException + { + try + { + socket.setTcpNoDelay(true); + if (_soLingerTime >= 0) + socket.setSoLinger(true,_soLingerTime / 1000); + else + socket.setSoLinger(false,0); + } + catch (Exception e) + { + LOG.trace("",e); + } + } + + /* ------------------------------------------------------------ */ + public void customize(EndPoint endpoint, Request request) throws IOException + { + if (isForwarded()) + checkForwardedHeaders(endpoint,request); + } /* ------------------------------------------------------------ */ - /** - * @return The port to use when redirecting a request if a data constraint of confidential is - * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} + protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException + { + HttpFields httpFields = request.getConnection().getRequestFields(); + + // Do SSL first + if (getForwardedCipherSuiteHeader()!=null) + { + String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); + if (cipher_suite!=null) + request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); + } + if (getForwardedSslSessionIdHeader()!=null) + { + String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); + if(ssl_session_id!=null) + { + request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); + request.setScheme(HttpSchemes.HTTPS); + } + } + + // Retrieving headers from the request + String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); + String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); + String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); + String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); + + if (_hostHeader != null) + { + // Update host header + httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader); + request.setServerName(null); + request.setServerPort(-1); + request.getServerName(); + } + else if (forwardedHost != null) + { + // Update host header + httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost); + request.setServerName(null); + request.setServerPort(-1); + request.getServerName(); + } + else if (forwardedServer != null) + { + // Use provided server name + request.setServerName(forwardedServer); + } + + if (forwardedFor != null) + { + request.setRemoteAddr(forwardedFor); + InetAddress inetAddress = null; + + if (_useDNS) + { + try + { + inetAddress = InetAddress.getByName(forwardedFor); + } + catch (UnknownHostException e) + { + LOG.trace("",e); + } + } + + request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName()); + } + + if (forwardedProto != null) + { + request.setScheme(forwardedProto); + } + } + + /* ------------------------------------------------------------ */ + protected String getLeftMostFieldValue(HttpFields fields, String header) + { + if (header == null) + return null; + + String headerValue = fields.getStringField(header); + + if (headerValue == null) + return null; + + int commaIndex = headerValue.indexOf(','); + + if (commaIndex == -1) + { + // Single value + return headerValue; + } + + // The left-most value is the farthest downstream client + return headerValue.substring(0,commaIndex); + } + + /* ------------------------------------------------------------ */ + public void persist(EndPoint endpoint) throws IOException + { + } + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#getConfidentialPort() */ - int getConfidentialPort(); - + public int getConfidentialPort() + { + return _confidentialPort; + } + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#getConfidentialScheme() + */ + public String getConfidentialScheme() + { + return _confidentialScheme; + } + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server .Request) + */ + public boolean isIntegral(Request request) + { + return false; + } + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#getConfidentialPort() + */ + public int getIntegralPort() + { + return _integralPort; + } + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#getIntegralScheme() + */ + public String getIntegralScheme() + { + return _integralScheme; + } + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server.Request) + */ + public boolean isConfidential(Request request) + { + return _forwarded && request.getScheme().equalsIgnoreCase(HttpSchemes.HTTPS); + } /* ------------------------------------------------------------ */ /** - * @return The schema to use when redirecting a request if a data constraint of confidential is - * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} + * @param confidentialPort + * The confidentialPort to set. */ - String getConfidentialScheme(); - + public void setConfidentialPort(int confidentialPort) + { + _confidentialPort = confidentialPort; + } + + /* ------------------------------------------------------------ */ + /** + * @param confidentialScheme + * The confidentialScheme to set. + */ + public void setConfidentialScheme(String confidentialScheme) + { + _confidentialScheme = confidentialScheme; + } + /* ------------------------------------------------------------ */ /** - * @param request A request - * @return true if the request is confidential. This normally means the https schema has been used. + * @param integralPort + * The integralPort to set. + */ + public void setIntegralPort(int integralPort) + { + _integralPort = integralPort; + } + + /* ------------------------------------------------------------ */ + /** + * @param integralScheme + * The integralScheme to set. */ - boolean isConfidential(Request request); + public void setIntegralScheme(String integralScheme) + { + _integralScheme = integralScheme; + } + + /* ------------------------------------------------------------ */ + protected abstract void accept(int acceptorID) throws IOException, InterruptedException; + + /* ------------------------------------------------------------ */ + public void stopAccept(int acceptorID) throws Exception + { + } /* ------------------------------------------------------------ */ - /** Customize a request for an endpoint. - * Called on every request to allow customization of the request for - * the particular endpoint (eg security properties from a SSL connection). - * @param endpoint - * @param request - * @throws IOException + public boolean getResolveNames() + { + return _useDNS; + } + + /* ------------------------------------------------------------ */ + public void setResolveNames(boolean resolve) + { + _useDNS = resolve; + } + + /* ------------------------------------------------------------ */ + /** + * Is reverse proxy handling on? + * + * @return true if this connector is checking the x-forwarded-for/host/server headers */ - void customize(EndPoint endpoint, Request request) throws IOException; + public boolean isForwarded() + { + return _forwarded; + } /* ------------------------------------------------------------ */ - /** Persist an endpoint. - * Called after every request if the connection is to remain open. - * @param endpoint - * @throws IOException + /** + * Set reverse proxy handling. If set to true, then the X-Forwarded headers (or the headers set in their place) are looked for to set the request protocol, + * host, server and client ip. + * + * @param check + * true if this connector is checking the x-forwarded-for/host/server headers + * @see #setForwardedForHeader(String) + * @see #setForwardedHostHeader(String) + * @see #setForwardedProtoHeader(String) + * @see #setForwardedServerHeader(String) */ - void persist(EndPoint endpoint) throws IOException; - + public void setForwarded(boolean check) + { + if (check) + LOG.debug("{} is forwarded",this); + _forwarded = check; + } + /* ------------------------------------------------------------ */ - /** - * @return The hostname representing the interface to which - * this connector will bind, or null for all interfaces. - */ - String getHost(); - - /* ------------------------------------------------------------ */ - /** - * Set the hostname of the interface to bind to. - * @param hostname The hostname representing the interface to which - * this connector will bind, or null for all interfaces. - */ - void setHost(String hostname); + public String getHostHeader() + { + return _hostHeader; + } /* ------------------------------------------------------------ */ /** - * @param port The port to listen of for connections or 0 if any available - * port may be used. + * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. + * This value is only used if {@link #isForwarded()} is true. + * + * @param hostHeader + * The value of the host header to force. */ - void setPort(int port); - + public void setHostHeader(String hostHeader) + { + _hostHeader = hostHeader; + } + + /* ------------------------------------------------------------ */ + /* + * + * @see #setForwarded(boolean) + */ + public String getForwardedHostHeader() + { + return _forwardedHostHeader; + } + /* ------------------------------------------------------------ */ /** - * @return The configured port for the connector or 0 if any available - * port may be used. + * @param forwardedHostHeader + * The header name for forwarded hosts (default x-forwarded-host) + * @see #setForwarded(boolean) + */ + public void setForwardedHostHeader(String forwardedHostHeader) + { + _forwardedHostHeader = forwardedHostHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @return the header name for forwarded server. + * @see #setForwarded(boolean) */ - int getPort(); - + public String getForwardedServerHeader() + { + return _forwardedServerHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedServerHeader + * The header name for forwarded server (default x-forwarded-server) + * @see #setForwarded(boolean) + */ + public void setForwardedServerHeader(String forwardedServerHeader) + { + _forwardedServerHeader = forwardedServerHeader; + } + /* ------------------------------------------------------------ */ /** - * @return The actual port the connector is listening on or - * -1 if it has not been opened, or -2 if it has been closed. + * @see #setForwarded(boolean) + */ + public String getForwardedForHeader() + { + return _forwardedForHeader; + } + + /* ------------------------------------------------------------ */ + /** + * @param forwardedRemoteAddressHeader + * The header name for forwarded for (default x-forwarded-for) + * @see #setForwarded(boolean) */ - int getLocalPort(); - + public void setForwardedForHeader(String forwardedRemoteAddressHeader) + { + _forwardedForHeader = forwardedRemoteAddressHeader; + } + + /* ------------------------------------------------------------ */ + /** + * Get the forwardedProtoHeader. + * + * @return the forwardedProtoHeader (default X-Forwarded-For) + * @see #setForwarded(boolean) + */ + public String getForwardedProtoHeader() + { + return _forwardedProtoHeader; + } + /* ------------------------------------------------------------ */ /** - * @return Max Idle time for connections in milliseconds + * Set the forwardedProtoHeader. + * + * @param forwardedProtoHeader + * the forwardedProtoHeader to set (default X-Forwarded-For) + * @see #setForwarded(boolean) */ - int getMaxIdleTime(); - + public void setForwardedProtoHeader(String forwardedProtoHeader) + { + _forwardedProtoHeader = forwardedProtoHeader; + } + + /* ------------------------------------------------------------ */ /** - * @param ms Max Idle time for connections in milliseconds + * @return The header name holding a forwarded cipher suite (default null) */ - void setMaxIdleTime(int ms); - + public String getForwardedCipherSuiteHeader() + { + return _forwardedCipherSuiteHeader; + } + /* ------------------------------------------------------------ */ - int getLowResourceMaxIdleTime(); - void setLowResourceMaxIdleTime(int ms); - + /** + * @param forwardedCipherSuite + * The header name holding a forwarded cipher suite (default null) + */ + public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) + { + _forwardedCipherSuiteHeader = forwardedCipherSuite; + } + + /* ------------------------------------------------------------ */ + /** + * @return The header name holding a forwarded SSL Session ID (default null) + */ + public String getForwardedSslSessionIdHeader() + { + return _forwardedSslSessionIdHeader; + } + /* ------------------------------------------------------------ */ /** - * @return the underlying socket, channel, buffer etc. for the connector. + * @param forwardedSslSessionId + * The header name holding a forwarded SSL Session ID (default null) */ - Object getConnection(); - - + public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) + { + _forwardedSslSessionIdHeader = forwardedSslSessionId; + } + + public int getRequestBufferSize() + { + return _buffers.getRequestBufferSize(); + } + + public void setRequestBufferSize(int requestBufferSize) + { + _buffers.setRequestBufferSize(requestBufferSize); + } + + public int getRequestHeaderSize() + { + return _buffers.getRequestHeaderSize(); + } + + public void setRequestHeaderSize(int requestHeaderSize) + { + _buffers.setRequestHeaderSize(requestHeaderSize); + } + + public int getResponseBufferSize() + { + return _buffers.getResponseBufferSize(); + } + + public void setResponseBufferSize(int responseBufferSize) + { + _buffers.setResponseBufferSize(responseBufferSize); + } + + public int getResponseHeaderSize() + { + return _buffers.getResponseHeaderSize(); + } + + public void setResponseHeaderSize(int responseHeaderSize) + { + _buffers.setResponseHeaderSize(responseHeaderSize); + } + + public Type getRequestBufferType() + { + return _buffers.getRequestBufferType(); + } + + public Type getRequestHeaderType() + { + return _buffers.getRequestHeaderType(); + } + + public Type getResponseBufferType() + { + return _buffers.getResponseBufferType(); + } + + public Type getResponseHeaderType() + { + return _buffers.getResponseHeaderType(); + } + + public void setRequestBuffers(Buffers requestBuffers) + { + _buffers.setRequestBuffers(requestBuffers); + } + + public void setResponseBuffers(Buffers responseBuffers) + { + _buffers.setResponseBuffers(responseBuffers); + } + + public Buffers getRequestBuffers() + { + return _buffers.getRequestBuffers(); + } + + public Buffers getResponseBuffers() + { + return _buffers.getResponseBuffers(); + } + + public int getMaxBuffers() + { + return _buffers.getMaxBuffers(); + } + /* ------------------------------------------------------------ */ - /** - * @return true if names resolution should be done. - */ - boolean getResolveNames(); - - + @Override + public String toString() + { + return String.format("%s@%s:%d", + getClass().getSimpleName(), + getHost()==null?"0.0.0.0":getHost(), + getLocalPort()<=0?getPort():getLocalPort()); + } /* ------------------------------------------------------------ */ - /** Check if low on resources. - * For most connectors, low resources is measured by calling - * {@link Server#isLowOnThreads()} on the connector threadpool - * or the server threadpool if there is no connector threadpool. - * <p> - * For blocking connectors, low resources is used to trigger - * usage of {@link #getLowResourceMaxIdleTime()} for the timeout - * of an idle connection. - * <p> - * for non-blocking connectors, the number of connections is - * used instead of this method, to select the timeout of an - * idle connection. - * <p> - * For all connectors, low resources is used to trigger the - * usage of {@link #getLowResourceMaxIdleTime()} for read and - * write operations. - * - * @return true if this connector is low on resources. + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + private class Acceptor implements Runnable + { + int _acceptor = 0; + + Acceptor(int id) + { + _acceptor = id; + } + + /* ------------------------------------------------------------ */ + public void run() + { + Thread current = Thread.currentThread(); + String name; + synchronized (Connector.this) + { + if (_acceptorThreads == null) + return; + + _acceptorThreads[_acceptor] = current; + name = _acceptorThreads[_acceptor].getName(); + current.setName(name + " Acceptor" + _acceptor + " " + Connector.this); + } + int old_priority = current.getPriority(); + + try + { + current.setPriority(old_priority - _acceptorPriorityOffset); + while (isRunning() && getConnection() != null) + { + try + { + accept(_acceptor); + } + catch (EofException e) + { + LOG.trace("",e); + } + catch (IOException e) + { + LOG.trace("",e); + } + catch (InterruptedException x) + { + // Connector has been stopped + LOG.trace("",x); + } + catch (Throwable e) + { + LOG.warn("",e); + } + } + } + finally + { + current.setPriority(old_priority); + current.setName(name); + + synchronized (Connector.this) + { + if (_acceptorThreads != null) + _acceptorThreads[_acceptor] = null; + } + } + } + } + + /* ------------------------------------------------------------ */ + public String getName() + { + if (_name == null) + _name = (getHost() == null?"0.0.0.0":getHost()) + ":" + (getLocalPort() <= 0?getPort():getLocalPort()); + return _name; + } + + /* ------------------------------------------------------------ */ + public void setName(String name) + { + _name = name; + } + + /* ------------------------------------------------------------ */ + protected void connectionOpened(Connection connection) + { + } + + /* ------------------------------------------------------------ */ + protected void connectionUpgraded(Connection oldConnection, Connection newConnection) + { + } + + /* ------------------------------------------------------------ */ + protected void connectionClosed(Connection connection) + { + connection.onClose(); + } + + /* ------------------------------------------------------------ */ + /** + * @return the acceptorPriority */ - public boolean isLowResources(); + public int getAcceptorPriorityOffset() + { + return _acceptorPriorityOffset; + } + + /* ------------------------------------------------------------ */ + /** + * Set the priority offset of the acceptor threads. The priority is adjusted by this amount (default 0) to either favour the acceptance of new threads and + * newly active connections or to favour the handling of already dispatched connections. + * + * @param offset + * the amount to alter the priority of the acceptor threads. + */ + public void setAcceptorPriorityOffset(int offset) + { + _acceptorPriorityOffset = offset; + } + + /* ------------------------------------------------------------ */ + /** + * @return True if the the server socket will be opened in SO_REUSEADDR mode. + */ + public boolean getReuseAddress() + { + return _reuseAddress; + } + + /* ------------------------------------------------------------ */ + /** + * @param reuseAddress + * True if the the server socket will be opened in SO_REUSEADDR mode. + */ + public void setReuseAddress(boolean reuseAddress) + { + _reuseAddress = reuseAddress; + } + + /* ------------------------------------------------------------ */ + public final boolean isLowResources() + { + return _server.isLowOnThreads(); + } + + /* ------------------------------------------------------------ */ + private void updateNotEqual(AtomicLong valueHolder, long compare, long value) + { + long oldValue = valueHolder.get(); + while (compare != oldValue) + { + if (valueHolder.compareAndSet(oldValue,value)) + break; + oldValue = valueHolder.get(); + } + } + + // from old interface + public abstract void open() throws IOException; + public abstract void close() throws IOException; + public abstract int getLocalPort(); + public abstract Object getConnection(); }
--- a/src/org/eclipse/jetty/server/nio/AbstractNIOConnector.java Tue Oct 04 16:30:02 2016 -0600 +++ b/src/org/eclipse/jetty/server/nio/AbstractNIOConnector.java Tue Oct 04 20:11:48 2016 -0600 @@ -22,32 +22,32 @@ package org.eclipse.jetty.server.nio; import org.eclipse.jetty.io.Buffers.Type; -import org.eclipse.jetty.server.AbstractConnector; +import org.eclipse.jetty.server.Connector; -public abstract class AbstractNIOConnector extends AbstractConnector implements NIOConnector +public abstract class AbstractNIOConnector extends Connector implements NIOConnector { - public AbstractNIOConnector() - { - _buffers.setRequestBufferType(Type.DIRECT); - _buffers.setRequestHeaderType(Type.INDIRECT); - _buffers.setResponseBufferType(Type.DIRECT); - _buffers.setResponseHeaderType(Type.INDIRECT); - } + public AbstractNIOConnector() + { + _buffers.setRequestBufferType(Type.DIRECT); + _buffers.setRequestHeaderType(Type.INDIRECT); + _buffers.setResponseBufferType(Type.DIRECT); + _buffers.setResponseHeaderType(Type.INDIRECT); + } - /* ------------------------------------------------------------------------------- */ - public boolean getUseDirectBuffers() - { - return getRequestBufferType()==Type.DIRECT; - } + /* ------------------------------------------------------------------------------- */ + public boolean getUseDirectBuffers() + { + return getRequestBufferType()==Type.DIRECT; + } - /* ------------------------------------------------------------------------------- */ - /** - * @param direct If True (the default), the connector can use NIO direct buffers. - * Some JVMs have memory management issues (bugs) with direct buffers. - */ - public void setUseDirectBuffers(boolean direct) - { - _buffers.setRequestBufferType(direct?Type.DIRECT:Type.INDIRECT); - _buffers.setResponseBufferType(direct?Type.DIRECT:Type.INDIRECT); - } + /* ------------------------------------------------------------------------------- */ + /** + * @param direct If True (the default), the connector can use NIO direct buffers. + * Some JVMs have memory management issues (bugs) with direct buffers. + */ + public void setUseDirectBuffers(boolean direct) + { + _buffers.setRequestBufferType(direct?Type.DIRECT:Type.INDIRECT); + _buffers.setResponseBufferType(direct?Type.DIRECT:Type.INDIRECT); + } }
--- a/src/org/eclipse/jetty/server/ssl/SslConnector.java Tue Oct 04 16:30:02 2016 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.server.ssl; - -import java.io.File; -import java.security.SecureRandom; -import java.security.Security; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.TrustManagerFactory; - -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.util.ssl.SslContextFactory; - - -/* ------------------------------------------------------------ */ -/** The interface for SSL connectors and their configuration methods. - * - */ -public interface SslConnector extends Connector -{ - @Deprecated - public static final String DEFAULT_KEYSTORE_ALGORITHM=(Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm")); - @Deprecated - public static final String DEFAULT_TRUSTSTORE_ALGORITHM=(Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.TrustManagerFactory.algorithm")); - - /** Default value for the keystore location path. @deprecated */ - @Deprecated - public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator + ".keystore"; - - /** String name of key password property. @deprecated */ - @Deprecated - public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword"; - - /** String name of keystore password property. @deprecated */ - @Deprecated - public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password"; - - - /* ------------------------------------------------------------ */ - /** - * @return the instance of SslContextFactory associated with the connector - */ - public SslContextFactory getSslContextFactory(); - - /* ------------------------------------------------------------ */ - /** - * @return The array of Ciphersuite names to exclude from - * {@link SSLEngine#setEnabledCipherSuites(String[])} - * @deprecated - */ - @Deprecated - public abstract String[] getExcludeCipherSuites(); - - /* ------------------------------------------------------------ */ - /** - * @param cipherSuites The array of Ciphersuite names to exclude from - * {@link SSLEngine#setEnabledCipherSuites(String[])} - * @deprecated - */ - @Deprecated - public abstract void setExcludeCipherSuites(String[] cipherSuites); - - /* ------------------------------------------------------------ */ - /** - * @return The array of Ciphersuite names to include in - * {@link SSLEngine#setEnabledCipherSuites(String[])} - * @deprecated - */ - @Deprecated - public abstract String[] getIncludeCipherSuites(); - - /* ------------------------------------------------------------ */ - /** - * @param cipherSuites The array of Ciphersuite names to include in - * {@link SSLEngine#setEnabledCipherSuites(String[])} - * @deprecated - */ - @Deprecated - public abstract void setIncludeCipherSuites(String[] cipherSuites); - - /* ------------------------------------------------------------ */ - /** - * @param password The password for the key store - * @deprecated - */ - @Deprecated - public abstract void setPassword(String password); - - /* ------------------------------------------------------------ */ - /** - * @param password The password for the trust store - * @deprecated - */ - @Deprecated - public abstract void setTrustPassword(String password); - - /* ------------------------------------------------------------ */ - /** - * @param password The password (if any) for the specific key within - * the key store - * @deprecated - */ - @Deprecated - public abstract void setKeyPassword(String password); - - /* ------------------------------------------------------------ */ - /** - * @return The SSL protocol (default "TLS") passed to {@link SSLContext#getInstance(String, String)} - * @deprecated - */ - @Deprecated - public abstract String getProtocol(); - - /* ------------------------------------------------------------ */ - /** - * @param protocol The SSL protocol (default "TLS") passed to {@link SSLContext#getInstance(String, String)} - * @deprecated - */ - @Deprecated - public abstract void setProtocol(String protocol); - - /* ------------------------------------------------------------ */ - /** - * @param keystore The file or URL of the SSL Key store. - * @deprecated - */ - @Deprecated - public abstract void setKeystore(String keystore); - - /* ------------------------------------------------------------ */ - /** - * @return The file or URL of the SSL Key store. - * @deprecated - */ - @Deprecated - public abstract String getKeystore(); - - /* ------------------------------------------------------------ */ - /** - * @return The type of the key store (default "JKS") - * @deprecated - */ - @Deprecated - public abstract String getKeystoreType(); - - /* ------------------------------------------------------------ */ - /** - * @return True if SSL needs client authentication. - * @see SSLEngine#getNeedClientAuth() - * @deprecated - */ - @Deprecated - public abstract boolean getNeedClientAuth(); - - /* ------------------------------------------------------------ */ - /** - * @return True if SSL wants client authentication. - * @see SSLEngine#getWantClientAuth() - * @deprecated - */ - @Deprecated - public abstract boolean getWantClientAuth(); - - /* ------------------------------------------------------------ */ - /** - * @param needClientAuth True if SSL needs client authentication. - * @see SSLEngine#getNeedClientAuth() - * @deprecated - */ - @Deprecated - public abstract void setNeedClientAuth(boolean needClientAuth); - - /* ------------------------------------------------------------ */ - /** - * @param wantClientAuth True if SSL wants client authentication. - * @see SSLEngine#getWantClientAuth() - * @deprecated - */ - @Deprecated - public abstract void setWantClientAuth(boolean wantClientAuth); - - /* ------------------------------------------------------------ */ - /** - * @param keystoreType The type of the key store (default "JKS") - * @deprecated - */ - @Deprecated - public abstract void setKeystoreType(String keystoreType); - - /* ------------------------------------------------------------ */ - /** - * @return The SSL provider name, which if set is passed to - * {@link SSLContext#getInstance(String, String)} - * @deprecated - */ - @Deprecated - public abstract String getProvider(); - - /* ------------------------------------------------------------ */ - /** - * @return The algorithm name, which if set is passed to - * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} - * instance passed to {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)} - * @deprecated - */ - @Deprecated - public abstract String getSecureRandomAlgorithm(); - - /* ------------------------------------------------------------ */ - /** - * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory} - * @deprecated - */ - @Deprecated - public abstract String getSslKeyManagerFactoryAlgorithm(); - - /* ------------------------------------------------------------ */ - /** - * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory} - * @deprecated - */ - @Deprecated - public abstract String getSslTrustManagerFactoryAlgorithm(); - - /* ------------------------------------------------------------ */ - /** - * @return The file name or URL of the trust store location - * @deprecated - */ - @Deprecated - public abstract String getTruststore(); - - /* ------------------------------------------------------------ */ - /** - * @return The type of the trust store (default "JKS") - * @deprecated - */ - @Deprecated - public abstract String getTruststoreType(); - - /* ------------------------------------------------------------ */ - /** - * @param provider The SSL provider name, which if set is passed to - * {@link SSLContext#getInstance(String, String)} - * @deprecated - */ - @Deprecated - public abstract void setProvider(String provider); - - /* ------------------------------------------------------------ */ - /** - * @param algorithm The algorithm name, which if set is passed to - * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} - * instance passed to {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)} - * @deprecated - */ - @Deprecated - public abstract void setSecureRandomAlgorithm(String algorithm); - - /* ------------------------------------------------------------ */ - /** - * @param algorithm The algorithm name (default "SunX509") used by - * the {@link KeyManagerFactory} - * @deprecated - */ - @Deprecated - public abstract void setSslKeyManagerFactoryAlgorithm(String algorithm); - - /* ------------------------------------------------------------ */ - /** - * @param algorithm The algorithm name (default "SunX509") used by the {@link TrustManagerFactory} - * @deprecated - */ - @Deprecated - public abstract void setSslTrustManagerFactoryAlgorithm(String algorithm); - - /* ------------------------------------------------------------ */ - /** - * @param truststore The file name or URL of the trust store location - * @deprecated - */ - @Deprecated - public abstract void setTruststore(String truststore); - - /* ------------------------------------------------------------ */ - /** - * @param truststoreType The type of the trust store (default "JKS") - * @deprecated - */ - @Deprecated - public abstract void setTruststoreType(String truststoreType); - - /* ------------------------------------------------------------ */ - /** - * @param sslContext Set a preconfigured SSLContext - * @deprecated - */ - @Deprecated - public abstract void setSslContext(SSLContext sslContext); - - /* ------------------------------------------------------------ */ - /** - * @return The SSLContext - * @deprecated - */ - @Deprecated - public abstract SSLContext getSslContext(); - - - /* ------------------------------------------------------------ */ - /** - * @return True if SSL re-negotiation is allowed (default false) - * @deprecated - */ - @Deprecated - public boolean isAllowRenegotiate(); - - /* ------------------------------------------------------------ */ - /** - * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered - * a vulnerability in SSL/TLS with re-negotiation. If your JVM - * does not have CVE-2009-3555 fixed, then re-negotiation should - * not be allowed. - * @param allowRenegotiate true if re-negotiation is allowed (default false) - * @deprecated - */ - @Deprecated - public void setAllowRenegotiate(boolean allowRenegotiate); -}
--- a/src/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java Tue Oct 04 16:30:02 2016 -0600 +++ b/src/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java Tue Oct 04 20:11:48 2016 -0600 @@ -46,7 +46,7 @@ * * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector" */ -public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector +public class SslSelectChannelConnector extends SelectChannelConnector { private final SslContextFactory _sslContextFactory; private Buffers _sslBuffers;