Browse Source

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>
tags/v1.2.0.201112221803-r
Shawn O. Pearce 12 years ago
parent
commit
c1a9b2ae8b

+ 19
- 9
org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java View File

@@ -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());


+ 0
- 5
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java View File

@@ -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;

+ 6
- 1
org.eclipse.jgit/src/org/eclipse/jgit/util/io/UnionInputStream.java View File

@@ -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;

Loading…
Cancel
Save