From c9e2b0f565074474613c8fbee6dde86a9fcd2395 Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Sat, 8 Dec 2018 10:39:47 +0000 Subject: [PATCH] Add enxio classes from jnr-unixsocket These classes are removed from jnr-unixsocket and packaged here instead to avoid split-package problems in OSGi systems. --- .../AbstractNativeDatagramChannel.java | 79 ++++++++++ .../channels/AbstractNativeSocketChannel.java | 101 +++++++++++++ src/main/java/jnr/enxio/channels/Common.java | 136 ++++++++++++++++++ .../enxio/channels/NativeSocketChannel.java | 46 ++---- 4 files changed, 325 insertions(+), 37 deletions(-) create mode 100644 src/main/java/jnr/enxio/channels/AbstractNativeDatagramChannel.java create mode 100644 src/main/java/jnr/enxio/channels/AbstractNativeSocketChannel.java create mode 100644 src/main/java/jnr/enxio/channels/Common.java diff --git a/src/main/java/jnr/enxio/channels/AbstractNativeDatagramChannel.java b/src/main/java/jnr/enxio/channels/AbstractNativeDatagramChannel.java new file mode 100644 index 0000000..a48d6bc --- /dev/null +++ b/src/main/java/jnr/enxio/channels/AbstractNativeDatagramChannel.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Fritz Elfert + * + * This file is part of the JNR project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jnr.enxio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.DatagramChannel; +import java.nio.channels.spi.SelectorProvider; + +public abstract class AbstractNativeDatagramChannel extends DatagramChannel + implements ByteChannel, NativeSelectableChannel { + + private final Common common; + + public AbstractNativeDatagramChannel(int fd) { + this(NativeSelectorProvider.getInstance(), fd); + } + + AbstractNativeDatagramChannel(SelectorProvider provider, int fd) { + super(provider); + common = new Common(fd); + } + + public void setFD(int fd) { + common.setFD(fd); + } + + public final int getFD() { + return common.getFD(); + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + Native.close(common.getFD()); + } + + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + Native.setBlocking(common.getFD(), block); + } + + public int read(ByteBuffer dst) throws IOException { + return common.read(dst); + } + + @Override + public long read(ByteBuffer[] dsts, int offset, + int length) throws IOException { + return common.read(dsts, offset, length); + } + + public int write(ByteBuffer src) throws IOException { + return common.write(src); + } + + @Override + public long write(ByteBuffer[] srcs, int offset, + int length) throws IOException { + return common.write(srcs, offset, length); + } + +} diff --git a/src/main/java/jnr/enxio/channels/AbstractNativeSocketChannel.java b/src/main/java/jnr/enxio/channels/AbstractNativeSocketChannel.java new file mode 100644 index 0000000..65ead06 --- /dev/null +++ b/src/main/java/jnr/enxio/channels/AbstractNativeSocketChannel.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Marcus Linke + * + * This file is part of the JNR project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jnr.enxio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; + +import jnr.constants.platform.Shutdown; + +public abstract class AbstractNativeSocketChannel extends SocketChannel + implements ByteChannel, NativeSelectableChannel { + + private final Common common; + + public AbstractNativeSocketChannel(int fd) { + this(NativeSelectorProvider.getInstance(), fd); + } + + AbstractNativeSocketChannel(SelectorProvider provider, int fd) { + super(provider); + common = new Common(fd); + } + + public void setFD(int fd) { + common.setFD(fd); + } + + public final int getFD() { + return common.getFD(); + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + Native.close(common.getFD()); + } + + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + Native.setBlocking(common.getFD(), block); + } + + public int read(ByteBuffer dst) throws IOException { + return common.read(dst); + } + + @Override + public long read(ByteBuffer[] dsts, int offset, + int length) throws IOException { + return common.read(dsts, offset, length); + } + + public int write(ByteBuffer src) throws IOException { + return common.write(src); + } + + @Override + public long write(ByteBuffer[] srcs, int offset, + int length) throws IOException { + return common.write(srcs, offset, length); + } + + @Override + public SocketChannel shutdownInput() throws IOException { + int n = Native.shutdown(common.getFD(), SHUT_RD); + if (n < 0) { + throw new IOException(Native.getLastErrorString()); + } + return this; + } + + @Override + public SocketChannel shutdownOutput() throws IOException { + int n = Native.shutdown(common.getFD(), SHUT_WR); + if (n < 0) { + throw new IOException(Native.getLastErrorString()); + } + return this; + } + + private static final int SHUT_RD = Shutdown.SHUT_RD.intValue(); + private static final int SHUT_WR = Shutdown.SHUT_WR.intValue(); +} diff --git a/src/main/java/jnr/enxio/channels/Common.java b/src/main/java/jnr/enxio/channels/Common.java new file mode 100644 index 0000000..66ac609 --- /dev/null +++ b/src/main/java/jnr/enxio/channels/Common.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016 Fritz Elfert + * + * This file is part of the JNR project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jnr.enxio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import jnr.constants.platform.Errno; + +/** + * Helper class, providing common methods. + */ +final class Common { + + private int _fd = -1; + + Common(int fd) { + _fd = fd; + } + + void setFD(int fd) { + _fd = fd; + } + + int getFD() { + return _fd; + } + + int read(ByteBuffer dst) throws IOException { + + ByteBuffer buffer = ByteBuffer.allocate(dst.remaining()); + + int n = Native.read(_fd, buffer); + + buffer.flip(); + + dst.put(buffer); + + switch (n) { + case 0: + return -1; + + case -1: + Errno lastError = Native.getLastError(); + switch (lastError) { + case EAGAIN: + case EWOULDBLOCK: + return 0; + + default: + throw new IOException(Native.getLastErrorString()); + } + + default: { + + return n; + } + } + } + + long read(ByteBuffer[] dsts, int offset, int length) + throws IOException { + long total = 0; + + for (int i = 0; i < length; i++) { + ByteBuffer dst = dsts[offset + i]; + long read = read(dst); + if (read == -1) { + return read; + } + total += read; + } + + return total; + } + + int write(ByteBuffer src) throws IOException { + + int r = src.remaining(); + + ByteBuffer buffer = ByteBuffer.allocate(r); + + buffer.put(src); + + buffer.position(0); + + int n = Native.write(_fd, buffer); + + if (n >=0 ) { + if (n < r) { + src.position(src.position()-(r-n)); + } + } else { + switch (Native.getLastError()) { + case EAGAIN: + case EWOULDBLOCK: + src.position(src.position()-r); + return 0; + default: + throw new IOException(Native.getLastErrorString()); + } + } + + return n; + } + + long write(ByteBuffer[] srcs, int offset, int length) + throws IOException { + + long result = 0; + int index = 0; + + for (index = offset; index < length; index++) { + result += write(srcs[index]); + } + + return result; + } + +} diff --git a/src/main/java/jnr/enxio/channels/NativeSocketChannel.java b/src/main/java/jnr/enxio/channels/NativeSocketChannel.java index 445ba1a..082ead1 100644 --- a/src/main/java/jnr/enxio/channels/NativeSocketChannel.java +++ b/src/main/java/jnr/enxio/channels/NativeSocketChannel.java @@ -29,7 +29,7 @@ import java.nio.channels.spi.SelectorProvider; public class NativeSocketChannel extends AbstractSelectableChannel implements ByteChannel, NativeSelectableChannel { - private final int fd; + private final Common common; private final int validOps; public NativeSocketChannel(int fd) { @@ -42,18 +42,18 @@ public class NativeSocketChannel extends AbstractSelectableChannel NativeSocketChannel(SelectorProvider provider, int fd, int ops) { super(provider); - this.fd = fd; + common = new Common(fd); this.validOps = ops; } @Override protected void implCloseSelectableChannel() throws IOException { - Native.close(fd); + Native.close(common.getFD()); } @Override protected void implConfigureBlocking(boolean block) throws IOException { - Native.setBlocking(fd, block); + Native.setBlocking(common.getFD(), block); } @Override @@ -61,54 +61,26 @@ public class NativeSocketChannel extends AbstractSelectableChannel return validOps; } public final int getFD() { - return fd; + return common.getFD(); } public int read(ByteBuffer dst) throws IOException { - int n = Native.read(fd, dst); - switch (n) { - case 0: - return -1; - - case -1: - switch (Native.getLastError()) { - case EAGAIN: - case EWOULDBLOCK: - return 0; - - default: - throw new IOException(Native.getLastErrorString()); - } - - default: - return n; - } + return common.read(dst); } public int write(ByteBuffer src) throws IOException { - int n = Native.write(fd, src); - if (n < 0) { - switch (Native.getLastError()) { - case EAGAIN: - case EWOULDBLOCK: - return 0; - default: - throw new IOException(Native.getLastErrorString()); - } - } - - return n; + return common.write(src); } public void shutdownInput() throws IOException { - int n = Native.shutdown(fd, SHUT_RD); + int n = Native.shutdown(common.getFD(), SHUT_RD); if (n < 0) { throw new IOException(Native.getLastErrorString()); } } public void shutdownOutput() throws IOException { - int n = Native.shutdown(fd, SHUT_WR); + int n = Native.shutdown(common.getFD(), SHUT_WR); if (n < 0) { throw new IOException(Native.getLastErrorString()); } -- 2.19.1