You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by da...@apache.org on 2016/12/06 05:01:01 UTC

[4/6] incubator-trafficcontrol git commit: TR - add ability to use NIO for custom tomcat connector

TR - add ability to use NIO for custom tomcat connector

(cherry picked from commit d069d9dd8ee814cf9c559e2ff78e0312b52a17ca)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b2154dcc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b2154dcc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b2154dcc

Branch: refs/heads/psql-rebase
Commit: b2154dcc2b3c7e0462ce7032cfe9866a0350b8e3
Parents: 7afccdb
Author: trevorackerman <tr...@gmail.com>
Authored: Tue Nov 22 11:32:42 2016 -0700
Committer: Dave Neuman <ne...@apache.org>
Committed: Mon Dec 5 14:35:54 2016 -0700

----------------------------------------------------------------------
 .../protocol/LanguidNioProtocol.java            | 118 +++++++++++++++++++
 .../traffic_router/protocol/LanguidPoller.java  |  22 ++--
 .../protocol/LanguidProtocol.java               |   2 +-
 .../protocol/RouterNioEndpoint.java             |  67 +++++++++++
 .../protocol/RouterProtocolHandler.java         |  29 +++++
 .../protocol/RouterSslImplementation.java       |   7 +-
 .../traffic_router/secure/KeyManager.java       |  21 +++-
 .../protocol/RouterSslImplementationTest.java   |   4 +-
 .../core/src/main/opt/tomcat/conf/server.xml    |   6 +-
 9 files changed, 255 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidNioProtocol.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidNioProtocol.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidNioProtocol.java
new file mode 100644
index 0000000..f81e96c
--- /dev/null
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidNioProtocol.java
@@ -0,0 +1,118 @@
+package com.comcast.cdn.traffic_control.traffic_router.protocol;
+
+import org.apache.coyote.http11.Http11NioProtocol;
+import org.apache.tomcat.util.net.SSLImplementation;
+import org.apache.tomcat.util.net.jsse.JSSEImplementation;
+
+public class LanguidNioProtocol extends Http11NioProtocol implements RouterProtocolHandler {
+	protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(LanguidNioProtocol.class);
+	private boolean ready = false;
+	private boolean initialized = false;
+	private String mbeanPath;
+	private String readyAttribute;
+	private String portAttribute;
+	private String sslClassName = JSSEImplementation.class.getCanonicalName();
+
+	public LanguidNioProtocol() {
+		log.warn("Serving wildcard certs for multiple domains");
+		ep = new RouterNioEndpoint();
+		setSSLImplementation(RouterSslImplementation.class.getCanonicalName());
+	}
+
+	public boolean setSSLImplementation(final String sslClassName) {
+		try {
+			Class.forName(sslClassName);
+			this.sslClassName = sslClassName;
+			return true;
+		} catch (ClassNotFoundException e) {
+			log.error("Failed to set SSL implementation to " + sslClassName + " class was not found, defaulting to JSSE");
+			this.sslClassName = JSSEImplementation.class.getCanonicalName();
+		}
+
+		return false;
+	}
+
+	@Override
+	@SuppressWarnings("PMD.SignatureDeclareThrowsException")
+	public void init() throws Exception {
+		if (!isReady()) {
+			log.info("Init called; creating thread to monitor the state of Traffic Router");
+			new LanguidPoller(this).start();
+			return;
+		}
+
+		log.info("Traffic Router is ready; calling super.init()");
+		super.init();
+
+		sslImplementation = (JSSEImplementation) SSLImplementation.getInstance(sslClassName);
+		setInitialized(true);
+	}
+
+	@Override
+	@SuppressWarnings("PMD.SignatureDeclareThrowsException")
+	public void start() throws Exception {
+		log.info("Start called; waiting for initialization to occur");
+
+		while (!isInitialized()) {
+			try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+				log.info("interrupted waiting for initialization");
+			}
+		}
+
+		log.info("Initialization complete; calling super.start()");
+
+		super.start();
+	}
+
+	@Override
+	public boolean isReady() {
+		return ready;
+	}
+
+	@Override
+	public void setReady(final boolean isReady) {
+		this.ready = isReady;
+	}
+
+	@Override
+	public boolean isInitialized() {
+		return initialized;
+	}
+
+	@Override
+	public void setInitialized(final boolean isInitialized) {
+		this.initialized = isInitialized;
+	}
+
+	@Override
+	public String getMbeanPath() {
+		return mbeanPath;
+	}
+
+	@Override
+	public void setMbeanPath(final String mbeanPath) {
+		this.mbeanPath = mbeanPath;
+	}
+
+	@Override
+	public String getReadyAttribute() {
+		return readyAttribute;
+	}
+
+	@Override
+	public void setReadyAttribute(final String readyAttribute) {
+		this.readyAttribute = readyAttribute;
+	}
+
+	@Override
+	public String getPortAttribute() {
+		return portAttribute;
+	}
+
+	@Override
+	public void setPortAttribute(final String portAttribute) {
+		this.portAttribute = portAttribute;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidPoller.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidPoller.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidPoller.java
index cf07128..c6f9a5d 100644
--- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidPoller.java
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidPoller.java
@@ -22,15 +22,15 @@ import javax.management.ObjectName;
 
 public class LanguidPoller extends Thread {
 	protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(LanguidPoller.class);
-	final private LanguidProtocol languidProtocol;
+	final private RouterProtocolHandler protocolHandler;
 
-	public LanguidPoller(final LanguidProtocol languidProtocol) {
-		this.languidProtocol = languidProtocol;
+	public LanguidPoller(final RouterProtocolHandler protocolHandler) {
+		this.protocolHandler = protocolHandler;
 	}
 
 	@Override
 	public void run() {
-		log.info("Waiting for state from mbean path " + languidProtocol.getMbeanPath());
+		log.info("Waiting for state from mbean path " + protocolHandler.getMbeanPath());
 
 		boolean firstTime = true;
 		while (true) {
@@ -38,9 +38,9 @@ public class LanguidPoller extends Thread {
 				final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
 				// See src/main/opt/conf/server.xml
 				// This is calling traffic-router:name=languidState
-				final ObjectName languidState = new ObjectName(languidProtocol.getMbeanPath());
-				final Object readyValue = mbs.getAttribute(languidState, languidProtocol.getReadyAttribute());
-				final Object portValue = mbs.getAttribute(languidState, languidProtocol.getPortAttribute());
+				final ObjectName languidState = new ObjectName(protocolHandler.getMbeanPath());
+				final Object readyValue = mbs.getAttribute(languidState, protocolHandler.getReadyAttribute());
+				final Object portValue = mbs.getAttribute(languidState, protocolHandler.getPortAttribute());
 				final boolean ready = Boolean.parseBoolean(readyValue.toString());
 				final int port = Integer.parseInt(portValue.toString());
 
@@ -50,12 +50,12 @@ public class LanguidPoller extends Thread {
 				
 				if (ready) {
 					if (port > 0) {
-						languidProtocol.setPort(port);
+						protocolHandler.setPort(port);
 					}
 
-					log.info("Traffic Router published the ready state; calling init() on our reference to Connector with a listen port of " + languidProtocol.getPort());
-					languidProtocol.setReady(true);
-					languidProtocol.init();
+					log.info("Traffic Router published the ready state; calling init() on our reference to Connector with a listen port of " + protocolHandler.getPort());
+					protocolHandler.setReady(true);
+					protocolHandler.init();
 					break;
 				}
 			} catch (Exception ex) {

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidProtocol.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidProtocol.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidProtocol.java
index cb624b2..a6ef342 100644
--- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidProtocol.java
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/LanguidProtocol.java
@@ -17,7 +17,7 @@ package com.comcast.cdn.traffic_control.traffic_router.protocol;
 
 import org.apache.coyote.http11.Http11Protocol;
 
-public class LanguidProtocol extends Http11Protocol {
+public class LanguidProtocol extends Http11Protocol implements RouterProtocolHandler {
 	protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(LanguidProtocol.class);
 	private boolean ready = false;
 	private boolean initialized = false;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
new file mode 100644
index 0000000..a93128b
--- /dev/null
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
@@ -0,0 +1,67 @@
+package com.comcast.cdn.traffic_control.traffic_router.protocol;
+
+import com.comcast.cdn.traffic_control.traffic_router.secure.KeyManager;
+import org.apache.tomcat.util.net.NioEndpoint;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.TrustManager;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.util.concurrent.CountDownLatch;
+
+public class RouterNioEndpoint extends NioEndpoint {
+
+	// The same code as its parent class except for SSL
+	@SuppressWarnings({"PMD.SignatureDeclareThrowsException", "PMD.NPathComplexity"})
+	public void init() throws Exception {
+
+		if (initialized) {
+			return;
+		}
+
+		serverSock = ServerSocketChannel.open();
+		serverSock.socket().setPerformancePreferences(socketProperties.getPerformanceConnectionTime(),
+			socketProperties.getPerformanceLatency(),
+			socketProperties.getPerformanceBandwidth());
+
+		final InetSocketAddress addr = (address != null ? new InetSocketAddress(address, port) : new InetSocketAddress(port));
+
+		serverSock.socket().bind(addr, backlog);
+		serverSock.configureBlocking(true); //mimic APR behavior
+		serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());
+
+		// Initialize thread count defaults for acceptor, poller
+		if (acceptorThreadCount == 0) {
+			// FIXME: Doesn't seem to work that well with multiple accept threads
+			acceptorThreadCount = 1;
+		}
+
+		if (pollerThreadCount <= 0) {
+			//minimum one poller thread
+			pollerThreadCount = 1;
+		}
+
+		stopLatch = new CountDownLatch(pollerThreadCount);
+
+		// Initialize SSL if needed
+		if (isSSLEnabled()) {
+			sslContext = SSLContext.getInstance(getSslProtocol());
+			sslContext.init(wrap(new javax.net.ssl.KeyManager[]{new KeyManager()}), new TrustManager[]{}, null);
+
+			final SSLSessionContext sessionContext = sslContext.getServerSessionContext();
+
+			if (sessionContext != null) {
+				sessionContext.setSessionCacheSize(sessionCacheSize);
+				sessionContext.setSessionTimeout(sessionTimeout);
+			}
+		}
+
+		if (oomParachute > 0) {
+			reclaimParachute(true);
+		}
+
+		selectorPool.open();
+		initialized = true;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterProtocolHandler.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterProtocolHandler.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterProtocolHandler.java
new file mode 100644
index 0000000..73f70d4
--- /dev/null
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterProtocolHandler.java
@@ -0,0 +1,29 @@
+package com.comcast.cdn.traffic_control.traffic_router.protocol;
+
+import org.apache.coyote.ProtocolHandler;
+
+public interface RouterProtocolHandler extends ProtocolHandler {
+	boolean isReady();
+
+	void setReady(final boolean isReady);
+
+	boolean isInitialized();
+
+	void setInitialized(final boolean isInitialized);
+
+	String getMbeanPath();
+
+	void setMbeanPath(final String mbeanPath);
+
+	String getReadyAttribute();
+
+	void setReadyAttribute(final String readyAttribute);
+
+	String getPortAttribute();
+
+	void setPortAttribute(final String portAttribute);
+
+	int getPort();
+
+	void setPort(int port);
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterSslImplementation.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterSslImplementation.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterSslImplementation.java
index a5a17c7..f8f9bb9 100644
--- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterSslImplementation.java
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterSslImplementation.java
@@ -15,16 +15,19 @@
 
 package com.comcast.cdn.traffic_control.traffic_router.protocol;
 
-import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SSLSupport;
 import org.apache.tomcat.util.net.ServerSocketFactory;
+import org.apache.tomcat.util.net.jsse.JSSEImplementation;
 
 import javax.net.ssl.SSLSession;
 import java.net.Socket;
 
-public class RouterSslImplementation extends SSLImplementation {
+public class RouterSslImplementation extends JSSEImplementation {
 	RouterJsseFactory factory = new RouterJsseFactory();
 
+	public RouterSslImplementation() throws ClassNotFoundException {
+	}
+
 	@Override
 	public String getImplementationName() {
 		return getClass().getSimpleName();

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/KeyManager.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/KeyManager.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/KeyManager.java
index 2eeb222..b199a6d 100644
--- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/KeyManager.java
+++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/KeyManager.java
@@ -17,7 +17,9 @@ package com.comcast.cdn.traffic_control.traffic_router.secure;
 
 import javax.net.ssl.ExtendedSSLSession;
 import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLSocket;
+import javax.net.ssl.X509ExtendedKeyManager;
 import javax.net.ssl.X509KeyManager;
 import java.net.Socket;
 import java.security.Principal;
@@ -29,7 +31,7 @@ import java.util.Optional;
 // Uses the in memory CertificateRegistry to provide dynamic key and certificate management for the router
 // The provided default implementation does not allow for the key store to change state
 // once the JVM loads the default classes.
-public class KeyManager implements X509KeyManager {
+public class KeyManager extends X509ExtendedKeyManager implements X509KeyManager {
 	private final static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(KeyManager.class);
 	private final CertificateRegistry certificateRegistry = CertificateRegistry.getInstance();
 
@@ -52,6 +54,16 @@ public class KeyManager implements X509KeyManager {
 	}
 
 	@Override
+	public String chooseEngineServerAlias(final String keyType, final Principal[] issuers, final SSLEngine engine) {
+		if (keyType == null) {
+			return null;
+		}
+
+		final ExtendedSSLSession sslSession = (ExtendedSSLSession) engine.getHandshakeSession();
+		return chooseServerAlias(sslSession);
+	}
+
+	@Override
 	public String chooseServerAlias(final String keyType, final Principal[] principals, final Socket socket) {
 		if (keyType == null) {
 			return null;
@@ -59,6 +71,10 @@ public class KeyManager implements X509KeyManager {
 
 		final SSLSocket sslSocket = (SSLSocket) socket;
 		final ExtendedSSLSession sslSession = (ExtendedSSLSession) sslSocket.getHandshakeSession();
+		return chooseServerAlias(sslSession);
+	}
+
+	private String chooseServerAlias(final ExtendedSSLSession sslSession) {
 		final List<SNIServerName> requestedNames = sslSession.getRequestedServerNames();
 
 		final StringBuilder stringBuilder = new StringBuilder();
@@ -79,7 +95,7 @@ public class KeyManager implements X509KeyManager {
 		if (stringBuilder.length() > 0) {
 			log.warn("No certificate registry aliases matching " + stringBuilder.toString());
 		} else {
-			log.warn("Client " + sslSocket.getRemoteSocketAddress() + " did not send any Server Name Indicators");
+			log.warn("Client " + sslSession.getPeerHost() + " did not send any Server Name Indicators");
 		}
 		return null;
 	}
@@ -103,4 +119,5 @@ public class KeyManager implements X509KeyManager {
 		log.error("No private key for alias " + alias);
 		return null;
 	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/connector/src/test/java/protocol/RouterSslImplementationTest.java
----------------------------------------------------------------------
diff --git a/traffic_router/connector/src/test/java/protocol/RouterSslImplementationTest.java b/traffic_router/connector/src/test/java/protocol/RouterSslImplementationTest.java
index 438096a..c794da3 100644
--- a/traffic_router/connector/src/test/java/protocol/RouterSslImplementationTest.java
+++ b/traffic_router/connector/src/test/java/protocol/RouterSslImplementationTest.java
@@ -31,12 +31,12 @@ import static org.hamcrest.Matchers.instanceOf;
 @PrepareForTest({RouterSslImplementation.class, JSSEFactory.class})
 public class RouterSslImplementationTest {
 	@Test
-	public void itReturnsItsName() {
+	public void itReturnsItsName() throws Exception {
 		assertThat(new RouterSslImplementation().getImplementationName(), equalTo("RouterSslImplementation"));
 	}
 
 	@Test
-	public void itReturnsRouterSslServerSocketFactory() {
+	public void itReturnsRouterSslServerSocketFactory() throws Exception {
 		assertThat(new RouterSslImplementation().getServerSocketFactory(), instanceOf(RouterSslServerSocketFactory.class));
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b2154dcc/traffic_router/core/src/main/opt/tomcat/conf/server.xml
----------------------------------------------------------------------
diff --git a/traffic_router/core/src/main/opt/tomcat/conf/server.xml b/traffic_router/core/src/main/opt/tomcat/conf/server.xml
index fe24a96..e7b6e26 100644
--- a/traffic_router/core/src/main/opt/tomcat/conf/server.xml
+++ b/traffic_router/core/src/main/opt/tomcat/conf/server.xml
@@ -32,13 +32,13 @@
 		at /docs/config/service.html -->
 
 	<Service name="traffic_router_core">
-		<Connector port="80" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidProtocol" maxThreads="10000"
+		<Connector port="80" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol" maxThreads="10000"
 				   connectionTimeout="20000" mbeanPath="traffic-router:name=languidState" readyAttribute="Ready" portAttribute="Port"/>
-		<Connector port="443" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidProtocol" maxThreads="10000"
+		<Connector port="443" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol" maxThreads="10000"
 				   scheme="https" secure="true" SSLEnabled="true"
 				   clientAuth="false" sslProtocol="TLS"
 				   connectionTimeout="20000" mbeanPath="traffic-router:name=languidState" readyAttribute="Ready" portAttribute="SecurePort"/>
-		<Connector port="3333" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidProtocol" maxThreads="10000"
+		<Connector port="3333" protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol" maxThreads="10000"
 				   connectionTimeout="20000" mbeanPath="traffic-router:name=languidState" readyAttribute="Ready" portAttribute="ApiPort"/>
 		<Engine name="traffic_router_core" defaultHost="localhost">
 			<Host name="localhost" appBase="/opt/traffic_router/webapps/core/">