459845 - Support upgrade from http1 to http2

functioning implementation.  Not exactly the most elegant solution, but works with nghttp2 -u
This commit is contained in:
Greg Wilkins 2015-03-19 12:02:54 +11:00
parent e21d24b035
commit caacebc223
5 changed files with 50 additions and 7 deletions

View File

@ -106,6 +106,12 @@ public class HttpURI
_fragment = fragment;
}
/* ------------------------------------------------------------ */
public HttpURI(HttpURI uri)
{
this(uri._scheme,uri._host,uri._port,uri._path,uri._param,uri._query,uri._fragment);
}
/* ------------------------------------------------------------ */
public HttpURI(String uri)
{

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.http;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.jetty.http.MetaData.Request;
public class MetaData implements Iterable<HttpField>
{
private HttpVersion _httpVersion;
@ -153,6 +155,12 @@ public class MetaData implements Iterable<HttpField>
this(method, new HttpURI(scheme, hostPort.getHost(), hostPort.getPort(), uri), version, fields, contentLength);
}
public Request(Request request)
{
this(request.getMethod(),new HttpURI(request.getURI()), request.getVersion(), new HttpFields(request.getFields()), request.getContentLength());
}
// TODO MetaData should be immuttable!!!
public void recycle()
{
super.recycle();

View File

@ -453,6 +453,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
flusher.iterate();
}
@Override
public void settings(SettingsFrame frame, Callback callback)
{
@ -643,6 +644,20 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
return null;
}
}
public IStream createUpgradeStream()
{
// SPEC: upgrade stream is id=1 and can't exceed maximum
remoteStreamCount.incrementAndGet();
IStream stream = newStream(1);
streams.put(1,stream);
updateLastStreamId(1);
stream.setIdleTimeout(getStreamIdleTimeout());
flowControl.onStreamCreated(stream, false);
if (LOG.isDebugEnabled())
LOG.debug("Created upgrade {}", stream);
return stream;
}
protected IStream newStream(int streamId)
{

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http.MetaData.Request;
import org.eclipse.jetty.http2.HTTP2Connection;
@ -53,6 +54,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
private final Queue<HttpChannelOverHTTP2> channels = new ConcurrentArrayQueue<>();
private final ServerSessionListener listener;
private final HttpConfiguration httpConfig;
private MetaData.Request upgrade;
public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, Parser parser, ISession session, int inputBufferSize, ServerSessionListener listener)
{
@ -74,6 +76,17 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
{
super.onOpen();
notifyAccept(getSession());
if (upgrade!=null)
{
MetaData.Request request=upgrade;
upgrade=null;
// TODO get rid of the downcasts below
IStream stream = ((HTTP2Session)getSession()).createUpgradeStream();
Connector connector = ((HTTP2ServerConnectionFactory.HTTPServerSessionListener)listener).getConnector();
push(connector,stream,request);
}
}
private void notifyAccept(ISession session)
@ -127,7 +140,6 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
return channel;
}
public boolean upgrade(Request request, HttpFields response101)
{
if (HttpMethod.PRI.is(request.getMethod()))
@ -153,11 +165,8 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
// SPEC: the required reply to this SETTINGS frame is the 101 response.
session.onSettings(frame, false);
// TODO use the metadata a response
// Create stream 1
// half close it
// arrange for the request meta data to be handled AFTER the subsequesnt #onOpen call
// TODO why is the metadata recycled???? it should me immutable!!! Oh well guess we have to create a new copy
upgrade=new MetaData.Request(request);
}
return true;

View File

@ -76,7 +76,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
return !HTTP2Cipher.isBlackListProtocol(tlsProtocol) || !HTTP2Cipher.isBlackListCipher(tlsCipher);
}
private class HTTPServerSessionListener extends ServerSessionListener.Adapter implements Stream.Listener
public class HTTPServerSessionListener extends ServerSessionListener.Adapter implements Stream.Listener
{
private final Connector connector;
private final EndPoint endPoint;
@ -87,6 +87,11 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
this.endPoint = endPoint;
}
public Connector getConnector()
{
return connector;
}
@Override
public Map<Integer, Integer> onPreface(Session session)
{