Small refactoring of HTTP/2 upgrade code.

This commit is contained in:
Simone Bordet 2015-03-12 19:08:09 +01:00
parent 79fb2a4083
commit feed8ea158
5 changed files with 90 additions and 56 deletions

View File

@ -56,7 +56,7 @@ public class HTTP2Connection extends AbstractConnection implements Connection.Up
this.executionStrategy = ExecutionStrategy.Factory.instanceFor(producer, executor);
}
protected ISession getSession()
public ISession getSession()
{
return session;
}

View File

@ -216,6 +216,12 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
@Override
public void onSettings(SettingsFrame frame)
{
// SPEC: SETTINGS frame MUST be replied.
onSettings(frame, true);
}
public void onSettings(SettingsFrame frame, boolean reply)
{
if (frame.isReply())
return;
@ -287,9 +293,11 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
}
notifySettings(this, frame);
// SPEC: SETTINGS frame MUST be replied.
SettingsFrame reply = new SettingsFrame(Collections.<Integer, Integer>emptyMap(), true);
settings(reply, Callback.Adapter.INSTANCE);
if (reply)
{
SettingsFrame replyFrame = new SettingsFrame(Collections.<Integer, Integer>emptyMap(), true);
settings(replyFrame, Callback.Adapter.INSTANCE);
}
}
@Override

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.http2.parser;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.http2.ErrorCode;
import org.eclipse.jetty.http2.Flags;
@ -165,6 +166,45 @@ public class SettingsBodyParser extends BodyParser
return true;
}
public static SettingsFrame parseBody(final ByteBuffer buffer)
{
final int bodyLength = buffer.remaining();
final AtomicReference<SettingsFrame> frameRef = new AtomicReference<>();
SettingsBodyParser parser = new SettingsBodyParser(null, null)
{
@Override
protected int getStreamId()
{
return 0;
}
@Override
protected int getBodyLength()
{
return bodyLength;
}
@Override
protected boolean onSettings(Map<Integer, Integer> settings)
{
frameRef.set(new SettingsFrame(settings, false));
return true;
}
@Override
protected boolean connectionFailure(ByteBuffer buffer, int error, String reason)
{
frameRef.set(null);
return false;
}
};
if (bodyLength == 0)
parser.emptyBody(buffer);
else
parser.parse(buffer);
return frameRef.get();
}
private enum State
{
PREPARE, SETTING_ID, SETTING_ID_BYTES, SETTING_VALUE, SETTING_VALUE_BYTES

View File

@ -24,8 +24,8 @@ import java.util.Map;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.ErrorCode;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.HTTP2Cipher;
import org.eclipse.jetty.http2.HTTP2Session;
import org.eclipse.jetty.http2.IStream;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
@ -86,39 +86,21 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
MetaData.Request request = (MetaData.Request) attachment;
if (LOG.isDebugEnabled())
LOG.debug("{} upgraded {}",this,request.toString()+request.getFields());
final byte[] settings = B64Code.decodeRFC4648URL(request.getFields().getField(HttpHeader.HTTP2_SETTINGS).getValue());
String value = request.getFields().getField(HttpHeader.HTTP2_SETTINGS).getValue();
final byte[] settings = B64Code.decodeRFC4648URL(value);
if (LOG.isDebugEnabled())
LOG.debug("{} settings {}",this,TypeUtil.toHexString(settings));
SettingsBodyParser parser = new SettingsBodyParser(null,null)
{
@Override
protected int getStreamId()
{
return 0;
}
@Override
protected int getBodyLength()
{
return settings.length;
}
@Override
protected boolean onSettings(Map<Integer, Integer> settings)
{
SettingsFrame frame = new SettingsFrame(settings, false);
// TODO something with this frame?
reset();
return true;
}
};
parser.parse(BufferUtil.toBuffer(settings));
SettingsFrame frame = SettingsBodyParser.parseBody(BufferUtil.toBuffer(settings));
if (frame == null)
throw new IllegalArgumentException(String.format("Invalid %s header value: %s", HttpHeader.HTTP2_SETTINGS, value));
HTTP2Session session = (HTTP2Session)connection.getSession();
// SPEC: the required reply to this SETTINGS frame is the 101 response.
session.onSettings(frame, false);
// TODO use the metadata to push a response
}

View File

@ -828,30 +828,14 @@ public class BufferUtil
public static ByteBuffer toBuffer(String s)
{
return ByteBuffer.wrap(s.getBytes(StandardCharsets.ISO_8859_1));
}
public static ByteBuffer toDirectBuffer(String s)
{
byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
buf.flip();
return buf;
return toBuffer(s, StandardCharsets.ISO_8859_1);
}
public static ByteBuffer toBuffer(String s, Charset charset)
{
return ByteBuffer.wrap(s.getBytes(charset));
}
public static ByteBuffer toDirectBuffer(String s, Charset charset)
{
byte[] bytes = s.getBytes(charset);
ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
buf.flip();
return buf;
if (s == null)
return EMPTY_BUFFER;
return toBuffer(s.getBytes(charset));
}
/**
@ -861,9 +845,11 @@ public class BufferUtil
* the byte array to back buffer with.
* @return ByteBuffer with provided byte array, in flush mode
*/
public static ByteBuffer toBuffer(byte array[])
public static ByteBuffer toBuffer(byte[] array)
{
return ByteBuffer.wrap(array);
if (array == null)
return EMPTY_BUFFER;
return toBuffer(array, 0, array.length);
}
/**
@ -879,9 +865,27 @@ public class BufferUtil
*/
public static ByteBuffer toBuffer(byte array[], int offset, int length)
{
if (array == null)
return EMPTY_BUFFER;
return ByteBuffer.wrap(array, offset, length);
}
public static ByteBuffer toDirectBuffer(String s)
{
return toDirectBuffer(s, StandardCharsets.ISO_8859_1);
}
public static ByteBuffer toDirectBuffer(String s, Charset charset)
{
if (s == null)
return EMPTY_BUFFER;
byte[] bytes = s.getBytes(charset);
ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
buf.flip();
return buf;
}
public static ByteBuffer toMappedBuffer(File file) throws IOException
{
try (RandomAccessFile raf = new RandomAccessFile(file, "r"))