INT-2936 Fix TCP Binary DeSerialization with NIO

Inadvertent sign extension on binary data with bit 7 set
causes early termination of binary deserializers.

The ChannelInputStream (which replaced the piped input
and output streams) failed to mask off the top 24 bits
of "normal" bytes received, causing Deserializers to
believe the stream was closed.

Add a mask of 0xff to bytes read.

Add a test case.
This commit is contained in:
Gary Russell
2013-02-16 09:38:14 -05:00
committed by Mark Fisher
parent 05cd1694c2
commit f48d175e83
2 changed files with 16 additions and 2 deletions

View File

@@ -69,7 +69,7 @@ public class TcpNioConnection extends TcpConnectionSupport {
private volatile long lastSend;
private AtomicInteger executionControl = new AtomicInteger();
private final AtomicInteger executionControl = new AtomicInteger();
private volatile boolean writingToPipe;
@@ -560,7 +560,7 @@ public class TcpNioConnection extends TcpConnectionSupport {
}
}
int bite;
bite = this.currentBuffer[this.currentOffset++];
bite = this.currentBuffer[this.currentOffset++] & 0xff;
this.available.decrementAndGet();
if (this.currentOffset >= this.currentBuffer.length) {
this.currentBuffer = null;

View File

@@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.logging.Log;
@@ -31,7 +32,9 @@ import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.ip.tcp.connection.TcpNioConnection.ChannelInputStream;
import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer;
import org.springframework.integration.test.util.TestUtils;
/**
* @author Gary Russell
@@ -68,4 +71,15 @@ public class TcpNetConnectionTests {
log.get());
}
@Test
public void testBinary() throws Exception {
SocketChannel socketChannel = mock(SocketChannel.class);
Socket socket = mock(Socket.class);
when(socketChannel.socket()).thenReturn(socket);
TcpNioConnection connection = new TcpNioConnection(socketChannel, true, false, null, null);
ChannelInputStream inputStream = TestUtils.getPropertyValue(connection, "channelInputStream", ChannelInputStream.class);
inputStream.write(new byte[] {(byte) 0x80}, 1);
assertEquals(0x80, inputStream.read());
}
}