464629 JDK8 Socket customization
Added the SocketCustomizationListener class which may be added as a bean to either a Connector or a ConnectionFactory so that customizations may be made per connector by connection type or even per connection factory. SSL is unwrapped.
This commit is contained in:
parent
37738d15e5
commit
8b39e7ffb8
|
@ -19,17 +19,20 @@
|
|||
package org.eclipse.jetty.http2.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SocketCustomizationListener;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
||||
|
@ -39,13 +42,17 @@ public class HTTP2CServer extends Server
|
|||
{
|
||||
HttpConfiguration config = new HttpConfiguration();
|
||||
// HTTP + HTTP/2 connector
|
||||
ServerConnector http = new ServerConnector(this,new HttpConnectionFactory(config), new HTTP2CServerConnectionFactory(config));
|
||||
http.setPort(port);
|
||||
addConnector(http);
|
||||
|
||||
HttpConnectionFactory http1 = new HttpConnectionFactory(config);
|
||||
HTTP2CServerConnectionFactory http2c = new HTTP2CServerConnectionFactory(config);
|
||||
ServerConnector connector = new ServerConnector(this,http1,http2c);
|
||||
connector.setPort(port);
|
||||
addConnector(connector);
|
||||
|
||||
((QueuedThreadPool)getThreadPool()).setName("server");
|
||||
|
||||
setHandler(new SimpleHandler());
|
||||
|
||||
}
|
||||
|
||||
public static void main(String... args ) throws Exception
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.eclipse.jetty.io;
|
|||
import java.io.Closeable;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.component.Container;
|
||||
|
||||
/**
|
||||
* <p>A {@link Connection} is associated to an {@link EndPoint} so that I/O events
|
||||
* happening on the {@link EndPoint} can be processed by the {@link Connection}.</p>
|
||||
|
@ -86,6 +88,16 @@ public interface Connection extends Closeable
|
|||
void onUpgradeTo(ByteBuffer prefilled);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* <p>A Listener for connection events.</p>
|
||||
* <p>Listeners can be added to a {@link Connection} to get open and close events.
|
||||
* The AbstractConnectionFactory implements a pattern where objects implement
|
||||
* this interface that have been added via {@link Container#addBean(Object)} to
|
||||
* the Connector or ConnectionFactory are added as listeners to all new connections
|
||||
* </p>
|
||||
*/
|
||||
public interface Listener
|
||||
{
|
||||
public void onOpened(Connection connection);
|
||||
|
|
|
@ -29,6 +29,19 @@ import org.eclipse.jetty.util.ArrayUtil;
|
|||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Abstract ConnectionFactory
|
||||
* <p>Provides the common handling for {@link ConnectionFactory} implementations including:<ul>
|
||||
* <li>Protocol identification
|
||||
* <li>Configuration of new Connections:<ul>
|
||||
* <li>Setting inputbuffer size
|
||||
* <li>Calling {@link Connection#addListener(Connection.Listener)} for all
|
||||
* Connection.Listener instances found as beans on the {@link Connector} and this {@link ConnectionFactory}
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory
|
||||
{
|
||||
private final String _protocol;
|
||||
|
@ -73,12 +86,17 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
|
|||
{
|
||||
connection.setInputBufferSize(getInputBufferSize());
|
||||
|
||||
// Add Connection.Listeners from Connector
|
||||
if (connector instanceof ContainerLifeCycle)
|
||||
{
|
||||
ContainerLifeCycle aggregate = (ContainerLifeCycle)connector;
|
||||
for (Connection.Listener listener : aggregate.getBeans(Connection.Listener.class))
|
||||
connection.addListener(listener);
|
||||
}
|
||||
// Add Connection.Listeners from this factory
|
||||
for (Connection.Listener listener : getBeans(Connection.Listener.class))
|
||||
connection.addListener(listener);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 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.net.Socket;
|
||||
|
||||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.Connection.Listener;
|
||||
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||
import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** A Connection Lister for customization of SocketConnections.
|
||||
* <p>Instances of this listener may be added to a {@link Connector} ( or
|
||||
* {@link ConnectionFactory}) so that they are applied to all connections
|
||||
* for that connector (or protocol) and thus allow additional Socket
|
||||
* configuration to be applied by implementing {@link #customize(Socket, Connection)}
|
||||
*/
|
||||
public class SocketCustomizationListener implements Listener
|
||||
{
|
||||
private final boolean _ssl;
|
||||
|
||||
/**
|
||||
* Construct with SSL unwrapping on.
|
||||
*/
|
||||
public SocketCustomizationListener()
|
||||
{
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ssl If True, then a Socket underlying an SSLConnection is unwrapped
|
||||
* and notified.
|
||||
*/
|
||||
public SocketCustomizationListener(boolean ssl)
|
||||
{
|
||||
_ssl=ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpened(Connection connection)
|
||||
{
|
||||
EndPoint endp = connection.getEndPoint();
|
||||
boolean ssl=false;
|
||||
|
||||
if (_ssl && endp instanceof DecryptedEndPoint)
|
||||
{
|
||||
endp = ((DecryptedEndPoint)endp).getSslConnection().getEndPoint();
|
||||
ssl=true;
|
||||
}
|
||||
|
||||
if (endp instanceof ChannelEndPoint)
|
||||
{
|
||||
Socket socket = ((ChannelEndPoint)endp).getSocket();
|
||||
customize(socket,connection.getClass(),ssl);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** This method may be extended to configure a socket on open
|
||||
* events.
|
||||
* @param socket The Socket to configure
|
||||
* @param connection The class of the connection (The socket may be wrapped
|
||||
* by an {@link SslConnection} prior to this connection).
|
||||
* @param ssl True if the socket is wrapped with an SslConnection
|
||||
*/
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -21,11 +21,12 @@ package org.eclipse.jetty.server.ssl;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.Queue;
|
||||
|
||||
import javax.net.ssl.SNIHostName;
|
||||
import javax.net.ssl.SNIServerName;
|
||||
|
@ -37,14 +38,17 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SocketCustomizationListener;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.ConcurrentArrayQueue;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.ssl.ExtendedSslContextFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
@ -57,6 +61,7 @@ import org.junit.Test;
|
|||
public class SslConnectionFactoryTest
|
||||
{
|
||||
Server _server;
|
||||
ServerConnector _connector;
|
||||
int _port;
|
||||
|
||||
@Before
|
||||
|
@ -84,7 +89,7 @@ public class SslConnectionFactoryTest
|
|||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
|
||||
|
||||
ServerConnector https = new ServerConnector(_server,
|
||||
ServerConnector https = _connector = new ServerConnector(_server,
|
||||
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
|
||||
new HttpConnectionFactory(https_config));
|
||||
https.setPort(0);
|
||||
|
@ -107,6 +112,8 @@ public class SslConnectionFactoryTest
|
|||
_port=https.getLocalPort();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@After
|
||||
public void after() throws Exception
|
||||
|
@ -198,4 +205,48 @@ public class SslConnectionFactoryTest
|
|||
clientContextFactory.stop();
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSocketCustomization() throws Exception
|
||||
{
|
||||
final Queue<String> history = new ConcurrentArrayQueue<>();
|
||||
|
||||
_connector.addBean(new SocketCustomizationListener()
|
||||
{
|
||||
@Override
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize connector "+connection+","+ssl);
|
||||
}
|
||||
});
|
||||
|
||||
_connector.getBean(SslConnectionFactory.class).addBean(new SocketCustomizationListener()
|
||||
{
|
||||
@Override
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize ssl "+connection+","+ssl);
|
||||
}
|
||||
});
|
||||
|
||||
_connector.getBean(HttpConnectionFactory.class).addBean(new SocketCustomizationListener()
|
||||
{
|
||||
@Override
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize http "+connection+","+ssl);
|
||||
}
|
||||
});
|
||||
|
||||
String response= getResponse("127.0.0.1",null);
|
||||
Assert.assertThat(response,Matchers.containsString("host=127.0.0.1"));
|
||||
|
||||
Assert.assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll());
|
||||
Assert.assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll());
|
||||
Assert.assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true",history.poll());
|
||||
Assert.assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true",history.poll());
|
||||
Assert.assertEquals(0,history.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue