aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Becker2013-08-28 08:45:25 (EDT)
committerThomas Becker2013-08-28 08:45:39 (EDT)
commitaf1abb7af636f76f9472699bebe0859947aef84e (patch)
tree44e69323b4ae1f4878ed2f9054847e5247d19947
parent20fbd95bf13d897c1f5d374d4153e994da66f6dc (diff)
downloadorg.eclipse.jetty.project-af1abb7af636f76f9472699bebe0859947aef84e.zip
org.eclipse.jetty.project-af1abb7af636f76f9472699bebe0859947aef84e.tar.gz
org.eclipse.jetty.project-af1abb7af636f76f9472699bebe0859947aef84e.tar.bz2
416026 improve error handlig in SPDY parsers
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java5
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java4
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java5
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java9
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java38
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java71
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java29
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java4
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/BrokenFrameTest.java287
-rw-r--r--jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpClientTransportOverSPDY.java2
-rw-r--r--jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpReceiverOverSPDY.java2
-rw-r--r--jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HTTPSPDYServerConnectionFactory.java2
-rw-r--r--jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java4
-rw-r--r--jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java6
-rw-r--r--jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/UnsupportedVersionTest.java3
15 files changed, 409 insertions, 62 deletions
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
index 5d1d5b9..66804fe 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
@@ -489,7 +489,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
@Override
public void onStreamException(StreamException x)
{
- notifyOnException(listener, x);
+ // TODO: rename to onFailure
+ notifyOnException(listener, x); //TODO: notify StreamFrameListener if exists?
rst(new RstInfo(x.getStreamId(), x.getStreamStatus()), new Callback.Adapter());
}
@@ -804,7 +805,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}", x, listener);
- listener.onException(x);
+ listener.onFailure(this, x);
}
}
catch (Exception xx)
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
index 7145790..698c4bb 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
@@ -111,7 +111,9 @@ public class StandardStream extends IdleTimeout implements IStream
@Override
protected void onIdleExpired(TimeoutException timeout)
{
- listener.onFailure(timeout);
+ StreamFrameListener listener = this.listener;
+ if (listener != null)
+ listener.onFailure(this, timeout);
}
@Override
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
index ffff51f..3ad1771 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
@@ -115,9 +115,10 @@ public interface SessionFrameListener extends EventListener
* SPDY session.</p>
* <p>Examples of such conditions are invalid frames received, corrupted headers compression state, etc.</p>
*
+ * @param session the session
* @param x the exception that caused the event processing failure
*/
- public void onException(Throwable x);
+ public void onFailure(Session session, Throwable x);
/**
@@ -154,7 +155,7 @@ public interface SessionFrameListener extends EventListener
}
@Override
- public void onException(Throwable x)
+ public void onFailure(Session session, Throwable x)
{
logger.info("", x);
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
index c8139e3..e3d9cd8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
@@ -54,7 +54,7 @@ public interface StreamFrameListener extends EventListener
* <p>Callback invoked when a push syn has been received on a stream.</p>
*
* @param stream the push stream just created
- * @param pushInfo
+ * @param pushInfo the push metadata
* @return a listener for stream events or null if there is no interest in being notified of stream events
*/
public StreamFrameListener onPush(Stream stream, PushInfo pushInfo);
@@ -71,9 +71,10 @@ public interface StreamFrameListener extends EventListener
/**
* <p>Callback invoked on errors.</p>
- * @param x
+ * @param stream the stream
+ * @param x the failure
*/
- public void onFailure(Throwable x);
+ public void onFailure(Stream stream, Throwable x);
/**
* <p>Empty implementation of {@link StreamFrameListener}</p>
@@ -102,7 +103,7 @@ public interface StreamFrameListener extends EventListener
}
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
index a253a19..c86d921 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
@@ -35,7 +35,8 @@ public abstract class ControlFrameParser
private short type;
private byte flags;
private int length;
- private ControlFrameBodyParser parser;
+ private ControlFrameBodyParser bodyParser;
+ private int bytesToSkip = 0;
public ControlFrameParser(CompressionFactory.Decompressor decompressor)
{
@@ -66,6 +67,12 @@ public abstract class ControlFrameParser
return length;
}
+ public void skip(int bytesToSkip)
+ {
+ state = State.SKIP;
+ this.bytesToSkip = bytesToSkip;
+ }
+
public boolean parse(ByteBuffer buffer)
{
while (buffer.hasRemaining())
@@ -140,9 +147,9 @@ public abstract class ControlFrameParser
// SPEC v3, 2.2.1: unrecognized control frames must be ignored
if (controlFrameType == null)
- parser = unknownParser;
+ bodyParser = unknownParser;
else
- parser = parsers.get(controlFrameType);
+ bodyParser = parsers.get(controlFrameType);
state = State.BODY;
@@ -153,13 +160,29 @@ public abstract class ControlFrameParser
}
case BODY:
{
- if (parser.parse(buffer))
+ if (bodyParser.parse(buffer))
{
reset();
return true;
}
break;
}
+ case SKIP:
+ {
+ int remaining = buffer.remaining();
+ if (remaining >= bytesToSkip)
+ {
+ buffer.position(buffer.position() + bytesToSkip);
+ reset();
+ return true;
+ }
+ else
+ {
+ buffer.position(buffer.limit());
+ bytesToSkip = bytesToSkip - remaining;
+ return false;
+ }
+ }
default:
{
throw new IllegalStateException();
@@ -169,7 +192,7 @@ public abstract class ControlFrameParser
return false;
}
- private void reset()
+ void reset()
{
state = State.VERSION;
cursor = 0;
@@ -177,13 +200,14 @@ public abstract class ControlFrameParser
type = 0;
flags = 0;
length = 0;
- parser = null;
+ bodyParser = null;
+ bytesToSkip = 0;
}
protected abstract void onControlFrame(ControlFrame frame);
private enum State
{
- VERSION, VERSION_BYTES, TYPE, TYPE_BYTES, FLAGS, LENGTH, BODY
+ VERSION, VERSION_BYTES, TYPE, TYPE_BYTES, FLAGS, LENGTH, BODY, SKIP
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
index 2bc95ac..341e2e3 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
@@ -108,7 +108,14 @@ public class Parser
{
for (Listener listener : listeners)
{
- listener.onStreamException(x);
+ try
+ {
+ listener.onStreamException(x);
+ }
+ catch (Exception xx)
+ {
+ logger.debug("Could not notify listener " + listener, xx);
+ }
}
}
@@ -130,49 +137,52 @@ public class Parser
public void parse(ByteBuffer buffer)
{
+ logger.debug("Parsing {} bytes", buffer.remaining());
try
{
- logger.debug("Parsing {} bytes", buffer.remaining());
while (buffer.hasRemaining())
{
- switch (state)
+ try
{
- case CONTROL_BIT:
- {
- // We must only peek the first byte and not advance the buffer
- // because the 7 least significant bits may be relevant in data frames
- int currByte = buffer.get(buffer.position());
- boolean isControlFrame = (currByte & 0x80) == 0x80;
- state = isControlFrame ? State.CONTROL_FRAME : State.DATA_FRAME;
- break;
- }
- case CONTROL_FRAME:
+ switch (state)
{
- if (controlFrameParser.parse(buffer))
- reset();
- break;
- }
- case DATA_FRAME:
- {
- if (dataFrameParser.parse(buffer))
- reset();
- break;
- }
- default:
- {
- throw new IllegalStateException();
+ case CONTROL_BIT:
+ {
+ // We must only peek the first byte and not advance the buffer
+ // because the 7 least significant bits may be relevant in data frames
+ int currByte = buffer.get(buffer.position());
+ boolean isControlFrame = (currByte & 0x80) == 0x80;
+ state = isControlFrame ? State.CONTROL_FRAME : State.DATA_FRAME;
+ break;
+ }
+ case CONTROL_FRAME:
+ {
+ if (controlFrameParser.parse(buffer))
+ reset();
+ break;
+ }
+ case DATA_FRAME:
+ {
+ if (dataFrameParser.parse(buffer))
+ reset();
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
}
}
+ catch (StreamException x)
+ {
+ notifyStreamException(x);
+ }
}
}
catch (SessionException x)
{
notifySessionException(x);
}
- catch (StreamException x)
- {
- notifyStreamException(x);
- }
catch (Throwable x)
{
notifySessionException(new SessionException(SessionStatus.PROTOCOL_ERROR, x));
@@ -227,5 +237,4 @@ public class Parser
{
CONTROL_BIT, CONTROL_FRAME, DATA_FRAME
}
-
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
index 30deb7c..644ffd8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
@@ -85,8 +85,31 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
{
// Now we know the streamId, we can do the version check
// and if it is wrong, issue a RST_STREAM
- checkVersion(controlFrameParser.getVersion(), streamId);
-
+ try
+ {
+ checkVersion(controlFrameParser.getVersion(), streamId);
+ }
+ catch (StreamException e)
+ {
+ // We've already read 4 bytes of the streamId which are part of controlFrameParser.getLength
+ // so we need to substract those from the bytesToSkip.
+ int bytesToSkip = controlFrameParser.getLength() - 4;
+ int remaining = buffer.remaining();
+ if (remaining >= bytesToSkip)
+ {
+ buffer.position(buffer.position() + bytesToSkip);
+ controlFrameParser.reset();
+ reset();
+ }
+ else
+ {
+ int bytesToSkipInNextBuffer = bytesToSkip - remaining;
+ buffer.position(buffer.limit());
+ controlFrameParser.skip(bytesToSkipInNextBuffer);
+ reset();
+ }
+ throw e;
+ }
if (buffer.remaining() >= 4)
{
associatedStreamId = buffer.getInt() & 0x7F_FF_FF_FF;
@@ -122,8 +145,6 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
else
{
slot = (short)(currByte & 0xFF);
- if (slot < 0)
- throw new StreamException(streamId, StreamStatus.INVALID_CREDENTIALS);
cursor = 0;
state = State.HEADERS;
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
index aadb2dd..7a78174 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
@@ -152,7 +152,7 @@ public class StandardStreamTest
stream.setStreamFrameListener(new StreamFrameListener.Adapter()
{
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
assertThat("exception is a TimeoutException", x, is(instanceOf(TimeoutException.class)));
onFailCalledLatch.countDown();
@@ -173,7 +173,7 @@ public class StandardStreamTest
stream.setStreamFrameListener(new StreamFrameListener.Adapter()
{
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
assertThat("exception is a TimeoutException", x, is(instanceOf(TimeoutException.class)));
onFailCalledLatch.countDown();
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/BrokenFrameTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/BrokenFrameTest.java
new file mode 100644
index 0000000..ede69ca
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/BrokenFrameTest.java
@@ -0,0 +1,287 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.parser;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipException;
+
+import org.eclipse.jetty.io.MappedByteBufferPool;
+import org.eclipse.jetty.spdy.CompressionFactory;
+import org.eclipse.jetty.spdy.StreamException;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.frames.ControlFrame;
+import org.eclipse.jetty.spdy.frames.SynStreamFrame;
+import org.eclipse.jetty.spdy.generator.Generator;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.Fields;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class BrokenFrameTest
+{
+
+ @Test
+ public void testInvalidHeaderNameLength() throws Exception
+ {
+ Fields headers = new Fields();
+ headers.add("broken", "header");
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, headers);
+ Generator generator = new Generator(new MappedByteBufferPool(), new NoCompressionCompressionFactory.NoCompressionCompressor());
+
+ ByteBuffer bufferWithBrokenHeaderNameLength = generator.control(frame);
+ // Break the header name length to provoke the Parser to throw a StreamException
+ bufferWithBrokenHeaderNameLength.put(21, (byte)0);
+
+ ByteBuffer bufferWithValidSynStreamFrame = generator.control(frame);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ outputStream.write(BufferUtil.toArray(bufferWithBrokenHeaderNameLength));
+ outputStream.write(BufferUtil.toArray(bufferWithValidSynStreamFrame));
+
+ byte concatenatedFramesByteArray[] = outputStream.toByteArray();
+ ByteBuffer concatenatedBuffer = BufferUtil.toBuffer(concatenatedFramesByteArray);
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ Parser parser = new Parser(new NoCompressionCompressionFactory.NoCompressionDecompressor());
+ parser.addListener(new Parser.Listener.Adapter()
+ {
+ @Override
+ public void onControlFrame(ControlFrame frame)
+ {
+ latch.countDown();
+ }
+
+ @Override
+ public void onStreamException(StreamException x)
+ {
+ latch.countDown();
+ }
+ });
+ parser.parse(concatenatedBuffer);
+
+ assertThat(latch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
+ @Test
+ public void testInvalidVersion() throws Exception
+ {
+ Fields headers = new Fields();
+ headers.add("good", "header");
+ headers.add("another","header");
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, headers);
+ Generator generator = new Generator(new MappedByteBufferPool(), new NoCompressionCompressionFactory.NoCompressionCompressor());
+
+ ByteBuffer bufferWithBrokenVersion = generator.control(frame);
+ // Break the header name length to provoke the Parser to throw a StreamException
+ bufferWithBrokenVersion.put(1, (byte)4);
+
+ ByteBuffer bufferWithValidSynStreamFrame = generator.control(frame);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ outputStream.write(BufferUtil.toArray(bufferWithBrokenVersion));
+ outputStream.write(BufferUtil.toArray(bufferWithValidSynStreamFrame));
+
+ byte concatenatedFramesByteArray[] = outputStream.toByteArray();
+ ByteBuffer concatenatedBuffer = BufferUtil.toBuffer(concatenatedFramesByteArray);
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ Parser parser = new Parser(new NoCompressionCompressionFactory.NoCompressionDecompressor());
+ parser.addListener(new Parser.Listener.Adapter()
+ {
+ @Override
+ public void onControlFrame(ControlFrame frame)
+ {
+ latch.countDown();
+ }
+
+ @Override
+ public void onStreamException(StreamException x)
+ {
+ latch.countDown();
+ }
+ });
+ parser.parse(concatenatedBuffer);
+
+ assertThat(latch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
+ @Test
+ public void testInvalidVersionWithSplitBuffer() throws Exception
+ {
+ Fields headers = new Fields();
+ headers.add("good", "header");
+ headers.add("another","header");
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, headers);
+ Generator generator = new Generator(new MappedByteBufferPool(), new NoCompressionCompressionFactory.NoCompressionCompressor());
+
+ ByteBuffer bufferWithBrokenVersion = generator.control(frame);
+ // Break the header name length to provoke the Parser to throw a StreamException
+ bufferWithBrokenVersion.put(1, (byte)4);
+
+ ByteBuffer bufferWithValidSynStreamFrame = generator.control(frame);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ outputStream.write(BufferUtil.toArray(bufferWithBrokenVersion));
+ outputStream.write(BufferUtil.toArray(bufferWithValidSynStreamFrame));
+
+ byte concatenatedFramesByteArray[] = outputStream.toByteArray();
+ ByteBuffer concatenatedBuffer1 = BufferUtil.toBuffer(Arrays.copyOfRange(concatenatedFramesByteArray,0,20));
+ ByteBuffer concatenatedBuffer2 = BufferUtil.toBuffer(Arrays.copyOfRange(concatenatedFramesByteArray,20,
+ concatenatedFramesByteArray.length));
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ Parser parser = new Parser(new NoCompressionCompressionFactory.NoCompressionDecompressor());
+ parser.addListener(new Parser.Listener.Adapter()
+ {
+ @Override
+ public void onControlFrame(ControlFrame frame)
+ {
+ latch.countDown();
+ }
+
+ @Override
+ public void onStreamException(StreamException x)
+ {
+ latch.countDown();
+ }
+ });
+ parser.parse(concatenatedBuffer1);
+ parser.parse(concatenatedBuffer2);
+
+ assertThat(latch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
+ @Test
+ public void testInvalidVersionAndGoodFrameSplitInThreeBuffers() throws Exception
+ {
+ Fields headers = new Fields();
+ headers.add("good", "header");
+ headers.add("another","header");
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, headers);
+ Generator generator = new Generator(new MappedByteBufferPool(), new NoCompressionCompressionFactory.NoCompressionCompressor());
+
+ ByteBuffer bufferWithBrokenVersion = generator.control(frame);
+ // Break the header name length to provoke the Parser to throw a StreamException
+ bufferWithBrokenVersion.put(1, (byte)4);
+
+ ByteBuffer bufferWithValidSynStreamFrame = generator.control(frame);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ outputStream.write(BufferUtil.toArray(bufferWithBrokenVersion));
+ outputStream.write(BufferUtil.toArray(bufferWithValidSynStreamFrame));
+
+ byte concatenatedFramesByteArray[] = outputStream.toByteArray();
+ ByteBuffer concatenatedBuffer1 = BufferUtil.toBuffer(Arrays.copyOfRange(concatenatedFramesByteArray,0,20));
+ ByteBuffer concatenatedBuffer2 = BufferUtil.toBuffer(Arrays.copyOfRange(concatenatedFramesByteArray,20, 30));
+ ByteBuffer concatenatedBuffer3 = BufferUtil.toBuffer(Arrays.copyOfRange(concatenatedFramesByteArray,30,
+ concatenatedFramesByteArray.length));
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ Parser parser = new Parser(new NoCompressionCompressionFactory.NoCompressionDecompressor());
+ parser.addListener(new Parser.Listener.Adapter()
+ {
+ @Override
+ public void onControlFrame(ControlFrame frame)
+ {
+ latch.countDown();
+ }
+
+ @Override
+ public void onStreamException(StreamException x)
+ {
+ latch.countDown();
+ }
+ });
+ parser.parse(concatenatedBuffer1);
+ parser.parse(concatenatedBuffer2);
+ parser.parse(concatenatedBuffer3);
+
+ assertThat(latch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
+ private static class NoCompressionCompressionFactory implements CompressionFactory
+ {
+
+ @Override
+ public Compressor newCompressor()
+ {
+ return null;
+ }
+
+ @Override
+ public Decompressor newDecompressor()
+ {
+ return null;
+ }
+
+ public static class NoCompressionCompressor implements Compressor
+ {
+
+ private byte[] input;
+
+ @Override
+ public void setInput(byte[] input)
+ {
+ this.input = input;
+ }
+
+ @Override
+ public void setDictionary(byte[] dictionary)
+ {
+ }
+
+ @Override
+ public int compress(byte[] output)
+ {
+ System.arraycopy(input, 0, output, 0, input.length);
+ return input.length;
+ }
+ }
+
+ public static class NoCompressionDecompressor implements Decompressor
+ {
+ private byte[] input;
+
+ @Override
+ public void setDictionary(byte[] dictionary)
+ {
+ }
+
+ @Override
+ public void setInput(byte[] input)
+ {
+ this.input = input;
+ }
+
+ @Override
+ public int decompress(byte[] output) throws ZipException
+ {
+ System.arraycopy(input, 0, output, 0, input.length);
+ return input.length;
+ }
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpClientTransportOverSPDY.java b/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpClientTransportOverSPDY.java
index 2533b86..a1f0297 100644
--- a/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpClientTransportOverSPDY.java
+++ b/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpClientTransportOverSPDY.java
@@ -57,7 +57,7 @@ public class HttpClientTransportOverSPDY implements HttpClientTransport
SessionFrameListener.Adapter listener = new SessionFrameListener.Adapter()
{
@Override
- public void onException(Throwable x)
+ public void onFailure(Session session, Throwable x)
{
// TODO: is this correct ?
// TODO: if I get a stream error (e.g. invalid response headers)
diff --git a/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpReceiverOverSPDY.java b/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpReceiverOverSPDY.java
index e693c9a..bf726ea 100644
--- a/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpReceiverOverSPDY.java
+++ b/jetty-spdy/spdy-http-client-transport/src/main/java/org/eclipse/jetty/spdy/client/http/HttpReceiverOverSPDY.java
@@ -141,7 +141,7 @@ public class HttpReceiverOverSPDY extends HttpReceiver implements StreamFrameLis
}
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
HttpExchange exchange = getHttpExchange();
if (exchange == null)
diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HTTPSPDYServerConnectionFactory.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HTTPSPDYServerConnectionFactory.java
index 40f405d..92db5aa 100644
--- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HTTPSPDYServerConnectionFactory.java
+++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HTTPSPDYServerConnectionFactory.java
@@ -156,7 +156,7 @@ public class HTTPSPDYServerConnectionFactory extends SPDYServerConnectionFactory
}
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
LOG.debug(x);
}
diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java
index fce2585..329ff72 100644
--- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java
+++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java
@@ -171,7 +171,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
}
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
LOG.debug(x);
}
@@ -275,7 +275,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
}
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
LOG.debug(x);
}
diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java
index ac52419..9e6d454 100644
--- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java
+++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java
@@ -1496,7 +1496,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
new StreamFrameListener.Adapter()
{
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
assertThat("we got a TimeoutException", x, instanceOf(TimeoutException.class));
timeoutReceivedLatch.countDown();
@@ -1535,7 +1535,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
new StreamFrameListener.Adapter()
{
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
assertThat("we got a TimeoutException", x, instanceOf(TimeoutException.class));
timeoutReceivedLatch.countDown();
@@ -1580,7 +1580,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
new StreamFrameListener.Adapter()
{
@Override
- public void onFailure(Throwable x)
+ public void onFailure(Stream stream, Throwable x)
{
assertThat("we got a TimeoutException", x, instanceOf(TimeoutException.class));
timeoutReceivedLatch.countDown();
diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/UnsupportedVersionTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/UnsupportedVersionTest.java
index e3b2df0..5849544 100644
--- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/UnsupportedVersionTest.java
+++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/UnsupportedVersionTest.java
@@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.spdy.StandardCompressionFactory;
import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
@@ -58,7 +59,7 @@ public class UnsupportedVersionTest extends AbstractTest
}
@Override
- public void onException(Throwable x)
+ public void onFailure(Session session, Throwable x)
{
// Suppress exception logging for this test
}