diff options
-rw-r--r-- | luni/src/main/java/java/nio/DatagramChannelImpl.java | 22 | ||||
-rw-r--r-- | luni/src/main/java/java/nio/FileChannelImpl.java | 7 | ||||
-rw-r--r-- | luni/src/main/java/java/nio/SocketChannelImpl.java | 6 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Posix.java | 65 | ||||
-rw-r--r-- | luni/src/test/java/libcore/io/OsTest.java | 121 |
5 files changed, 176 insertions, 45 deletions
diff --git a/luni/src/main/java/java/nio/DatagramChannelImpl.java b/luni/src/main/java/java/nio/DatagramChannelImpl.java index 9008637..8dd6f29 100644 --- a/luni/src/main/java/java/nio/DatagramChannelImpl.java +++ b/luni/src/main/java/java/nio/DatagramChannelImpl.java @@ -274,15 +274,9 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException { SocketAddress retAddr = null; DatagramPacket receivePacket = new DatagramPacket(EmptyArray.BYTE, 0); - int oldposition = target.position(); - int received; do { - received = IoBridge.recvfrom(false, fd, target, 0, receivePacket, isConnected()); + IoBridge.recvfrom(false, fd, target, 0, receivePacket, isConnected()); if (receivePacket.getAddress() != null) { - // copy the data of received packet - if (received > 0) { - target.position(oldposition + received); - } retAddr = receivePacket.getSocketAddress(); break; } @@ -309,11 +303,7 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann int sendCount = 0; try { begin(); - int oldPosition = source.position(); sendCount = IoBridge.sendto(fd, source, 0, isa.getAddress(), isa.getPort()); - if (sendCount > 0) { - source.position(oldPosition + sendCount); - } if (!isBound) { onBind(true /* updateSocketState */); } @@ -336,10 +326,6 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann int readCount; if (target.isDirect() || target.hasArray()) { readCount = readImpl(target); - if (readCount > 0) { - target.position(target.position() + readCount); - } - } else { byte[] readArray = new byte[target.remaining()]; ByteBuffer readBuffer = ByteBuffer.wrap(readArray); @@ -406,11 +392,7 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann return 0; } - int writeCount = writeImpl(src); - if (writeCount > 0) { - src.position(src.position() + writeCount); - } - return writeCount; + return writeImpl(src); } /** diff --git a/luni/src/main/java/java/nio/FileChannelImpl.java b/luni/src/main/java/java/nio/FileChannelImpl.java index d72b9f0..b560864 100644 --- a/luni/src/main/java/java/nio/FileChannelImpl.java +++ b/luni/src/main/java/java/nio/FileChannelImpl.java @@ -323,9 +323,7 @@ final class FileChannelImpl extends FileChannel { } finally { end(completed && bytesRead >= 0); } - if (bytesRead > 0) { - buffer.position(buffer.position() + bytesRead); - } + return bytesRead; } @@ -508,9 +506,6 @@ final class FileChannelImpl extends FileChannel { } finally { end(completed); } - if (bytesWritten > 0) { - buffer.position(buffer.position() + bytesWritten); - } return bytesWritten; } diff --git a/luni/src/main/java/java/nio/SocketChannelImpl.java b/luni/src/main/java/java/nio/SocketChannelImpl.java index d5cb716..d09aaef 100644 --- a/luni/src/main/java/java/nio/SocketChannelImpl.java +++ b/luni/src/main/java/java/nio/SocketChannelImpl.java @@ -340,9 +340,6 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorChannel { begin(); } readCount = IoBridge.recvfrom(true, fd, dst, 0, null, false); - if (readCount > 0) { - dst.position(dst.position() + readCount); - } } finally { if (isBlocking()) { end(readCount > 0); @@ -404,9 +401,6 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorChannel { begin(); } writeCount = IoBridge.sendto(fd, src, 0, null, 0); - if (writeCount > 0) { - src.position(src.position() + writeCount); - } } finally { if (isBlocking()) { end(writeCount >= 0); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index 73b0dc4..1772c34 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -112,11 +112,17 @@ public final class Posix implements Os { public native void posix_fallocate(FileDescriptor fd, long offset, long length) throws ErrnoException; public native int prctl(int option, long arg2, long arg3, long arg4, long arg5) throws ErrnoException; public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException { + final int bytesRead; + final int position = buffer.position(); + if (buffer.isDirect()) { - return preadBytes(fd, buffer, buffer.position(), buffer.remaining(), offset); + bytesRead = preadBytes(fd, buffer, position, buffer.remaining(), offset); } else { - return preadBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), offset); + bytesRead = preadBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), offset); } + + maybeUpdateBufferPosition(buffer, position, bytesRead); + return bytesRead; } public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -124,11 +130,17 @@ public final class Posix implements Os { } private native int preadBytes(FileDescriptor fd, Object buffer, int bufferOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException; public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException { + final int bytesWritten; + final int position = buffer.position(); + if (buffer.isDirect()) { - return pwriteBytes(fd, buffer, buffer.position(), buffer.remaining(), offset); + bytesWritten = pwriteBytes(fd, buffer, position, buffer.remaining(), offset); } else { - return pwriteBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), offset); + bytesWritten = pwriteBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), offset); } + + maybeUpdateBufferPosition(buffer, position, bytesWritten); + return bytesWritten; } public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -136,11 +148,17 @@ public final class Posix implements Os { } private native int pwriteBytes(FileDescriptor fd, Object buffer, int bufferOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException; public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException { + final int bytesRead; + final int position = buffer.position(); + if (buffer.isDirect()) { - return readBytes(fd, buffer, buffer.position(), buffer.remaining()); + bytesRead = readBytes(fd, buffer, position, buffer.remaining()); } else { - return readBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining()); + bytesRead = readBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining()); } + + maybeUpdateBufferPosition(buffer, position, bytesRead); + return bytesRead; } public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -150,11 +168,17 @@ public final class Posix implements Os { public native String readlink(String path) throws ErrnoException; public native int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException; public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { + final int bytesReceived; + final int position = buffer.position(); + if (buffer.isDirect()) { - return recvfromBytes(fd, buffer, buffer.position(), buffer.remaining(), flags, srcAddress); + bytesReceived = recvfromBytes(fd, buffer, position, buffer.remaining(), flags, srcAddress); } else { - return recvfromBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), flags, srcAddress); + bytesReceived = recvfromBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), flags, srcAddress); } + + maybeUpdateBufferPosition(buffer, position, bytesReceived); + return bytesReceived; } public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -165,11 +189,17 @@ public final class Posix implements Os { public native void rename(String oldPath, String newPath) throws ErrnoException; public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException; public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { + final int bytesSent; + final int position = buffer.position(); + if (buffer.isDirect()) { - return sendtoBytes(fd, buffer, buffer.position(), buffer.remaining(), flags, inetAddress, port); + bytesSent = sendtoBytes(fd, buffer, position, buffer.remaining(), flags, inetAddress, port); } else { - return sendtoBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), flags, inetAddress, port); + bytesSent = sendtoBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), flags, inetAddress, port); } + + maybeUpdateBufferPosition(buffer, position, bytesSent); + return bytesSent; } public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -212,11 +242,16 @@ public final class Posix implements Os { public native void unsetenv(String name) throws ErrnoException; public native int waitpid(int pid, MutableInt status, int options) throws ErrnoException; public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException { + final int bytesWritten; + final int position = buffer.position(); if (buffer.isDirect()) { - return writeBytes(fd, buffer, buffer.position(), buffer.remaining()); + bytesWritten = writeBytes(fd, buffer, position, buffer.remaining()); } else { - return writeBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining()); + bytesWritten = writeBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining()); } + + maybeUpdateBufferPosition(buffer, position, bytesWritten); + return bytesWritten; } public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException { // This indirection isn't strictly necessary, but ensures that our public interface is type safe. @@ -224,4 +259,10 @@ public final class Posix implements Os { } private native int writeBytes(FileDescriptor fd, Object buffer, int offset, int byteCount) throws ErrnoException, InterruptedIOException; public native int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException; + + private static void maybeUpdateBufferPosition(ByteBuffer buffer, int originalPosition, int bytesReadOrWritten) { + if (bytesReadOrWritten > 0) { + buffer.position(bytesReadOrWritten + originalPosition); + } + } } diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java index cf28122..a0d1e5a 100644 --- a/luni/src/test/java/libcore/io/OsTest.java +++ b/luni/src/test/java/libcore/io/OsTest.java @@ -20,11 +20,14 @@ import android.system.StructUcred; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.InetUnixAddress; import java.net.ServerSocket; import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Locale; import junit.framework.TestCase; import static android.system.OsConstants.*; @@ -77,7 +80,7 @@ public class OsTest extends TestCase { assertEquals(Libcore.os.getgid(), credentials.gid); byte[] request = new byte[256]; - int requestLength = Libcore.os.read(clientFd, request, 0, request.length); + Libcore.os.read(clientFd, request, 0, request.length); String s = new String(request, "UTF-8"); byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8"); @@ -135,4 +138,120 @@ public class OsTest extends TestCase { assertEquals("Killed", Libcore.os.strsignal(9)); assertEquals("Unknown signal -1", Libcore.os.strsignal(-1)); } + + public void test_byteBufferPositions_write_pwrite() throws Exception { + FileOutputStream fos = new FileOutputStream(new File("/dev/null")); + FileDescriptor fd = fos.getFD(); + final byte[] contents = new String("goodbye, cruel world").getBytes(StandardCharsets.US_ASCII); + ByteBuffer byteBuffer = ByteBuffer.wrap(contents); + + byteBuffer.position(0); + int written = Libcore.os.write(fd, byteBuffer); + assertTrue(written > 0); + assertEquals(written, byteBuffer.position()); + + byteBuffer.position(4); + written = Libcore.os.write(fd, byteBuffer); + assertTrue(written > 0); + assertEquals(written + 4, byteBuffer.position()); + + byteBuffer.position(0); + written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); + assertTrue(written > 0); + assertEquals(written, byteBuffer.position()); + + byteBuffer.position(4); + written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); + assertTrue(written > 0); + assertEquals(written + 4, byteBuffer.position()); + + fos.close(); + } + + public void test_byteBufferPositions_read_pread() throws Exception { + FileInputStream fis = new FileInputStream(new File("/dev/zero")); + FileDescriptor fd = fis.getFD(); + ByteBuffer byteBuffer = ByteBuffer.allocate(64); + + byteBuffer.position(0); + int read = Libcore.os.read(fd, byteBuffer); + assertTrue(read > 0); + assertEquals(read, byteBuffer.position()); + + byteBuffer.position(4); + read = Libcore.os.read(fd, byteBuffer); + assertTrue(read > 0); + assertEquals(read + 4, byteBuffer.position()); + + byteBuffer.position(0); + read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); + assertTrue(read > 0); + assertEquals(read, byteBuffer.position()); + + byteBuffer.position(4); + read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); + assertTrue(read > 0); + assertEquals(read + 4, byteBuffer.position()); + + fis.close(); + } + + public void test_byteBufferPositions_sendto_recvfrom() throws Exception { + final FileDescriptor serverFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); + Libcore.os.bind(serverFd, InetAddress.getLoopbackAddress(), 0); + Libcore.os.listen(serverFd, 5); + + InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd); + + final Thread server = new Thread(new Runnable() { + public void run() { + try { + InetSocketAddress peerAddress = new InetSocketAddress(); + FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress); + + // Attempt to receive a maximum of 24 bytes from the client, and then + // close the connection. + ByteBuffer buffer = ByteBuffer.allocate(16); + int received = Libcore.os.recvfrom(clientFd, buffer, 0, null); + assertTrue(received > 0); + assertEquals(received, buffer.position()); + + ByteBuffer buffer2 = ByteBuffer.allocate(16); + buffer2.position(8); + received = Libcore.os.recvfrom(clientFd, buffer2, 0, null); + assertTrue(received > 0); + assertEquals(received + 8, buffer.position()); + + Libcore.os.close(clientFd); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + }); + + + server.start(); + + FileDescriptor clientFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); + Libcore.os.connect(clientFd, address.getAddress(), address.getPort()); + + final byte[] bytes = "good bye, cruel black hole with fancy distortion".getBytes(StandardCharsets.US_ASCII); + assertTrue(bytes.length > 24); + + ByteBuffer input = ByteBuffer.wrap(bytes); + input.position(0); + input.limit(16); + + int sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); + assertTrue(sent > 0); + assertEquals(sent, input.position()); + + input.position(16); + input.limit(24); + sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); + assertTrue(sent > 0); + assertEquals(sent + 16, input.position()); + + Libcore.os.close(clientFd); + } } |