diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2011-09-14 15:31:42 -0700 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2011-09-14 15:34:55 -0700 |
commit | c1a9b2ae8be6b0826b62021fe82a53de8783ea21 (patch) | |
tree | 061e847b479274bc214121ff420b45b23c82ad34 | |
parent | cc4e6109e40ac6f761b302b24bd6a793393090d5 (diff) | |
download | jgit-c1a9b2ae8be6b0826b62021fe82a53de8783ea21.tar.gz jgit-c1a9b2ae8be6b0826b62021fe82a53de8783ea21.zip |
Fix smart HTTP client stream alignment errors
The client's use of UnionInputStream was broken when combined with a
8192 byte buffer used by PackParser. A smart HTTP client connection
always pushes in the execute stateless RPC input stream after the
data stream has ended from the remote peer. At the end of the pack,
PackParser asked to fill a 8192 byte buffer, but if only e.g. 1000
bytes remained UnionInputStream went to the next stream and asked
it for input, which triggered a new RPC, and failed because there
was nothing pending in the request buffer.
Change UnionInputStream to only return what it consumed from a
single InputStream without invoking the next InputStream, just in
case that second InputStream happens to be one of these magical
ones that generates an RPC invocation.
Change-Id: I0e51a8e6fea1647e4d2e08ac9cfc69c2945ce4cb
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
3 files changed, 25 insertions, 15 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java index 5fd6816ec7..9fb323c4db 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java @@ -106,13 +106,21 @@ public class UnionInputStreamTest { u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); final byte[] r = new byte[5]; - assertEquals(5, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 1, 0, 2, 3, 4 }, r)); + assertEquals(3, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); assertEquals(1, u.read(r, 0, 5)); - assertEquals(5, r[0]); + assertEquals(3, r[0]); + assertEquals(2, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); assertEquals(-1, u.read(r, 0, 5)); } + private static byte[] slice(byte[] in, int len) { + byte[] r = new byte[len]; + System.arraycopy(in, 0, r, 0, len); + return r; + } + @Test public void testArrayConstructor() throws IOException { final UnionInputStream u = new UnionInputStream( @@ -121,10 +129,12 @@ public class UnionInputStreamTest { new ByteArrayInputStream(new byte[] { 4, 5 })); final byte[] r = new byte[5]; - assertEquals(5, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 1, 0, 2, 3, 4 }, r)); + assertEquals(3, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); assertEquals(1, u.read(r, 0, 5)); - assertEquals(5, r[0]); + assertEquals(3, r[0]); + assertEquals(2, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); assertEquals(-1, u.read(r, 0, 5)); } @@ -143,9 +153,9 @@ public class UnionInputStreamTest { u.add(new ByteArrayInputStream(new byte[] { 3 })); u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); assertEquals(0, u.skip(0)); - assertEquals(4, u.skip(4)); - assertEquals(4, u.read()); - assertEquals(1, u.skip(5)); + assertEquals(3, u.skip(3)); + assertEquals(3, u.read()); + assertEquals(2, u.skip(5)); assertEquals(0, u.skip(5)); assertEquals(-1, u.read()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java index 43ad98985d..1b78fcfc9a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -851,11 +851,6 @@ public class TransportHttp extends HttpTransport implements WalkTransport, } class HttpExecuteStream extends InputStream { - public int available() throws IOException { - execute(); - return 0; - } - public int read() throws IOException { execute(); return -1; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/UnionInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/UnionInputStream.java index f0183717a7..0df3775f11 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/UnionInputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/UnionInputStream.java @@ -148,8 +148,11 @@ public class UnionInputStream extends InputStream { len -= n; } else if (in == EOF) return 0 < cnt ? cnt : -1; - else + else { pop(); + if (0 < cnt) + break; + } } return cnt; } @@ -180,6 +183,8 @@ public class UnionInputStream extends InputStream { final int r = in.read(); if (r < 0) { pop(); + if (0 < cnt) + break; } else { cnt += 1; len -= 1; |