Jetty9 - Introduced NextProtoNego AsyncConnections to handle SSL with NPN.

This commit is contained in:
Simone Bordet 2012-07-27 21:54:09 +02:00
parent 369bc035fc
commit 592cb3432e
12 changed files with 318 additions and 236 deletions

View File

@ -172,7 +172,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param connection the connection just opened
*/
protected void connectionOpened(AsyncConnection connection)
public void connectionOpened(AsyncConnection connection)
{
connection.onOpen();
}
@ -182,7 +182,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param connection the connection just closed
*/
protected void connectionClosed(AsyncConnection connection)
public void connectionClosed(AsyncConnection connection)
{
connection.onClose();
}
@ -193,7 +193,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
* @param endpoint the endpoint holding the new connection
* @param oldConnection the previous connection
*/
protected void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
public void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
{
connectionClosed(oldConnection);
connectionOpened(endpoint.getAsyncConnection());

View File

@ -217,7 +217,7 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
}
@Override
protected void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
public void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
{
super.connectionUpgraded(endpoint, oldConnection);
SelectChannelConnector.this.connectionUpgraded(oldConnection, endpoint.getAsyncConnection());

View File

@ -1,16 +1,15 @@
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
// ========================================================================
// Copyright 2011-2012 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.spdy;

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
public class EmptyAsyncConnection extends AbstractAsyncConnection
{
public EmptyAsyncConnection(AsyncEndPoint endPoint)
{
super(endPoint, new Executor()
{
@Override
public void execute(Runnable command)
{
command.run();
}
});
}
@Override
public void onFillable()
{
}
}

View File

@ -1,18 +1,15 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ========================================================================
// Copyright 2011-2012 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.spdy;

View File

@ -1,16 +1,15 @@
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
// ========================================================================
// Copyright 2011-2012 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.spdy;

View File

@ -0,0 +1,101 @@
// ========================================================================
// Copyright 2011-2012 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.spdy;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class NextProtoNegoClientAsyncConnection extends AbstractAsyncConnection implements NextProtoNego.ClientProvider
{
private final Logger logger = Log.getLogger(getClass());
private final SocketChannel channel;
private final Object attachment;
private final SPDYClient client;
private volatile boolean completed;
public NextProtoNegoClientAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment, Executor executor, SPDYClient client)
{
super(endPoint, executor);
this.channel = channel;
this.attachment = attachment;
this.client = client;
}
@Override
public void onFillable()
{
while (true)
{
int filled = fill();
if (filled == 0 && !completed)
fillInterested();
if (filled <= 0)
break;
}
}
private int fill()
{
try
{
return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
}
catch (IOException x)
{
logger.debug(x);
getEndPoint().close();
return -1;
}
}
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
// Server does not support NPN, but this is a SPDY client, so hardcode SPDY
AsyncEndPoint endPoint = getEndPoint();
AsyncConnection connection = client.getDefaultAsyncConnectionFactory().newAsyncConnection(channel, endPoint, attachment);
client.replaceAsyncConnection(endPoint, connection);
completed = true;
}
@Override
public String selectProtocol(List<String> protocols)
{
String protocol = client.selectProtocol(protocols);
if (protocol == null)
return null;
AsyncEndPoint endPoint = getEndPoint();
AsyncConnection connection = client.getAsyncConnectionFactory(protocol).newAsyncConnection(channel, endPoint, attachment);
client.replaceAsyncConnection(endPoint, connection);
completed = true;
return protocol;
}
}

View File

@ -0,0 +1,94 @@
// ========================================================================
// Copyright 2011-2012 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.spdy;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.List;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class NextProtoNegoServerAsyncConnection extends AbstractAsyncConnection implements NextProtoNego.ServerProvider
{
private final Logger logger = Log.getLogger(getClass());
private final SocketChannel channel;
private final SPDYServerConnector connector;
private volatile boolean completed;
public NextProtoNegoServerAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, SPDYServerConnector connector)
{
super(endPoint, connector.findExecutor());
this.channel = channel;
this.connector = connector;
}
@Override
public void onFillable()
{
while (true)
{
int filled = fill();
if (filled == 0 && !completed)
fillInterested();
if (filled <= 0)
break;
}
}
private int fill()
{
try
{
return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
}
catch (IOException x)
{
logger.debug(x);
getEndPoint().close();
return -1;
}
}
@Override
public void unsupported()
{
AsyncConnectionFactory asyncConnectionFactory = connector.getDefaultAsyncConnectionFactory();
AsyncEndPoint endPoint = getEndPoint();
AsyncConnection connection = asyncConnectionFactory.newAsyncConnection(channel, endPoint, connector);
connector.replaceAsyncConnection(endPoint, connection);
completed = true;
}
@Override
public List<String> protocols()
{
return connector.provideProtocols();
}
@Override
public void protocolSelected(String protocol)
{
AsyncConnectionFactory asyncConnectionFactory = connector.getAsyncConnectionFactory(protocol);
AsyncEndPoint endPoint = getEndPoint();
AsyncConnection connection = asyncConnectionFactory.newAsyncConnection(channel, endPoint, connector);
connector.replaceAsyncConnection(endPoint, connection);
completed = true;
}
}

View File

@ -1,18 +1,15 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ========================================================================
// Copyright 2011-2012 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.spdy;

View File

@ -1,16 +1,15 @@
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
// ========================================================================
// Copyright 2011-2012 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.spdy;
@ -31,7 +30,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
@ -52,10 +50,11 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class SPDYClient
{
private final Map<String, AsyncConnectionFactory> factories = new ConcurrentHashMap<>();
private final AsyncConnectionFactory defaultAsyncConnectionFactory = new ClientSPDYAsyncConnectionFactory();
private final short version;
private final Factory factory;
private SocketAddress bindAddress;
private long idleTimeout = -1;
private volatile SocketAddress bindAddress;
private volatile long idleTimeout = -1;
private volatile int initialWindowSize = 65536;
protected SPDYClient(short version, Factory factory)
@ -166,6 +165,11 @@ public class SPDYClient
return factories.remove(protocol);
}
public AsyncConnectionFactory getDefaultAsyncConnectionFactory()
{
return defaultAsyncConnectionFactory;
}
protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
@ -180,6 +184,13 @@ public class SPDYClient
return FlowControlStrategyFactory.newFlowControlStrategy(version);
}
public void replaceAsyncConnection(AsyncEndPoint endPoint, AsyncConnection connection)
{
AsyncConnection oldConnection = endPoint.getAsyncConnection();
endPoint.setAsyncConnection(connection);
factory.selector.connectionUpgraded(endPoint, oldConnection);
}
public static class Factory extends AggregateLifeCycle
{
private final Map<String, AsyncConnectionFactory> factories = new ConcurrentHashMap<>();
@ -333,43 +344,13 @@ public class SPDYClient
super.onClose();
}
};
endPoint.setAsyncConnection(sslConnection);
final AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
NextProtoNego.put(engine, new NextProtoNego.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
// Server does not support NPN, but this is a SPDY client, so hardcode SPDY
ClientSPDYAsyncConnectionFactory connectionFactory = new ClientSPDYAsyncConnectionFactory();
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
sslEndPoint.setAsyncConnection(connection);
}
@Override
public String selectProtocol(List<String> protocols)
{
String protocol = client.selectProtocol(protocols);
if (protocol == null)
return null;
AsyncConnectionFactory connectionFactory = client.getAsyncConnectionFactory(protocol);
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
sslEndPoint.setAsyncConnection(connection);
return protocol;
}
});
AsyncConnection connection = new EmptyAsyncConnection(sslEndPoint);
AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
NextProtoNegoClientAsyncConnection connection = new NextProtoNegoClientAsyncConnection(channel, sslEndPoint, attachment, client.factory.threadPool, client);
sslEndPoint.setAsyncConnection(connection);
connectionOpened(connection);
startHandshake(engine);
NextProtoNego.put(engine, connection);
return sslConnection;
}
@ -387,18 +368,6 @@ public class SPDYClient
throw x;
}
}
private void startHandshake(SSLEngine engine)
{
try
{
engine.beginHandshake();
}
catch (SSLException x)
{
throw new RuntimeException(x);
}
}
}
}

View File

@ -1,16 +1,15 @@
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
// ========================================================================
// Copyright 2011-2012 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.spdy;
@ -30,7 +29,6 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
@ -38,7 +36,7 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
@ -189,7 +187,8 @@ public class SPDYServerConnector extends SelectChannelConnector
if (sslContextFactory != null)
{
final SSLEngine engine = newSSLEngine(sslContextFactory, channel);
SslConnection sslConnection = new SslConnection(bufferPool, findExecutor(), endPoint, engine)
Executor executor = findExecutor();
SslConnection sslConnection = new SslConnection(bufferPool, executor, endPoint, engine)
{
@Override
public void onClose()
@ -198,37 +197,13 @@ public class SPDYServerConnector extends SelectChannelConnector
super.onClose();
}
};
endPoint.setAsyncConnection(sslConnection);
final AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
NextProtoNego.put(engine, new NextProtoNego.ServerProvider()
{
@Override
public void unsupported()
{
AsyncConnectionFactory connectionFactory = getDefaultAsyncConnectionFactory();
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, SPDYServerConnector.this);
sslEndPoint.setAsyncConnection(connection);
}
@Override
public List<String> protocols()
{
return provideProtocols();
}
@Override
public void protocolSelected(String protocol)
{
AsyncConnectionFactory connectionFactory = getAsyncConnectionFactory(protocol);
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, SPDYServerConnector.this);
sslEndPoint.setAsyncConnection(connection);
}
});
AsyncConnection connection = new EmptyAsyncConnection(sslEndPoint);
NextProtoNegoServerAsyncConnection connection = new NextProtoNegoServerAsyncConnection(channel, sslEndPoint, this);
sslEndPoint.setAsyncConnection(connection);
getSelectorManager().connectionOpened(connection);
startHandshake(engine);
NextProtoNego.put(engine, connection);
return sslConnection;
}
@ -255,18 +230,6 @@ public class SPDYServerConnector extends SelectChannelConnector
return engine;
}
private void startHandshake(SSLEngine engine)
{
try
{
engine.beginHandshake();
}
catch (SSLException x)
{
throw new RuntimeException(x);
}
}
protected boolean sessionOpened(Session session)
{
// Add sessions only if the connector is not stopping
@ -302,6 +265,13 @@ public class SPDYServerConnector extends SelectChannelConnector
this.initialWindowSize = initialWindowSize;
}
public void replaceAsyncConnection(AsyncEndPoint endPoint, AsyncConnection connection)
{
AsyncConnection oldConnection = endPoint.getAsyncConnection();
endPoint.setAsyncConnection(connection);
getSelectorManager().connectionUpgraded(endPoint, oldConnection);
}
private class LazyExecutor implements Executor
{
@Override
@ -321,6 +291,6 @@ public class SPDYServerConnector extends SelectChannelConnector
super.dump(out,indent);
AggregateLifeCycle.dump(out, indent, new ArrayList<Session>(sessions));
}
}

View File

@ -1,16 +1,15 @@
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
// ========================================================================
// Copyright 2011-2012 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.spdy;