diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-10-05 02:44:18 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-10-05 02:44:18 +0000 |
commit | 2799793789d5b66c90efbd1a3eb56e0c1ec57f88 (patch) | |
tree | 9157197f502b6830af9cafe029fd3d47628a7ed6 /gnu/java/net/PlainSocketImpl.java | |
parent | 7516107c5abe26f7a4378017344eb9e449ebc28e (diff) | |
download | classpath-2799793789d5b66c90efbd1a3eb56e0c1ec57f88.tar.gz |
2006-10-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of HEAD-->generics for 2006/09/03-2006/10/04.
Diffstat (limited to 'gnu/java/net/PlainSocketImpl.java')
-rw-r--r-- | gnu/java/net/PlainSocketImpl.java | 352 |
1 files changed, 245 insertions, 107 deletions
diff --git a/gnu/java/net/PlainSocketImpl.java b/gnu/java/net/PlainSocketImpl.java index 47d05aa41..750243d5d 100644 --- a/gnu/java/net/PlainSocketImpl.java +++ b/gnu/java/net/PlainSocketImpl.java @@ -39,13 +39,24 @@ exception statement from your version. */ package gnu.java.net; +import gnu.java.nio.SelectorProviderImpl; +import gnu.java.nio.SocketChannelImpl; +import gnu.java.nio.VMChannel; +import gnu.java.security.action.GetSecurityPropertyAction; + +import java.io.EOFException; import java.io.InputStream; import java.io.IOException; +import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketImpl; +import java.net.SocketTimeoutException; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; /** * Written using on-line Java Platform 1.2 API Specification, as well @@ -63,17 +74,13 @@ import java.net.SocketImpl; * @author Nic Ferrier (nferrier@tapsellferrier.co.uk) * @author Aaron M. Renn (arenn@urbanophile.com) */ -public final class PlainSocketImpl extends SocketImpl +public class PlainSocketImpl extends SocketImpl { /** - * The OS file handle representing the socket. - * This is used for reads and writes to/from the socket and - * to close it. - * - * When the socket is closed this is reset to -1. + * The underlying plain socket VM implementation. */ - int native_fd = -1; + protected VMPlainSocketImpl impl; /** * A cached copy of the in stream for reading from the socket. @@ -90,7 +97,13 @@ public final class PlainSocketImpl extends SocketImpl * is being invoked on this socket. */ private boolean inChannelOperation; - + + /** + * The socket channel we use for IO operation. Package-private for + * use by inner classes. + */ + SocketChannelImpl channel; + /** * Indicates whether we should ignore whether any associated * channel is set to non-blocking mode. Certain operations @@ -117,29 +130,7 @@ public final class PlainSocketImpl extends SocketImpl */ public PlainSocketImpl() { - // Nothing to do here. - } - - protected void finalize() throws Throwable - { - synchronized (this) - { - if (native_fd != -1) - try - { - close(); - } - catch (IOException ex) - { - // Nothing we can do about it. - } - } - super.finalize(); - } - - public int getNativeFD() - { - return native_fd; + this.impl = new VMPlainSocketImpl(); } /** @@ -155,7 +146,29 @@ public final class PlainSocketImpl extends SocketImpl */ public void setOption(int optionId, Object value) throws SocketException { - VMPlainSocketImpl.setOption(this, optionId, value); + switch (optionId) + { + case IP_MULTICAST_IF: + case IP_MULTICAST_IF2: + throw new UnsupportedOperationException("FIXME"); + + case IP_MULTICAST_LOOP: + case SO_BROADCAST: + case SO_KEEPALIVE: + case SO_OOBINLINE: + case TCP_NODELAY: + case IP_TOS: + case SO_LINGER: + case SO_RCVBUF: + case SO_SNDBUF: + case SO_TIMEOUT: + case SO_REUSEADDR: + impl.setOption(optionId, value); + return; + + default: + throw new SocketException("cannot set option " + optionId); + } } /** @@ -171,17 +184,33 @@ public final class PlainSocketImpl extends SocketImpl */ public Object getOption(int optionId) throws SocketException { - return VMPlainSocketImpl.getOption(this, optionId); + if (optionId == SO_BINDADDR) + { + try + { + return channel.getVMChannel().getLocalAddress().getAddress(); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } + if (optionId == IP_MULTICAST_IF || optionId == IP_MULTICAST_IF2) + throw new UnsupportedOperationException ("can't get option " + + optionId + " yet"); + return impl.getOption(optionId); } public void shutdownInput() throws IOException { - VMPlainSocketImpl.shutdownInput(this); + impl.shutdownInput(); } public void shutdownOutput() throws IOException { - VMPlainSocketImpl.shutdownOutput(this); + impl.shutdownOutput(); } /** @@ -195,7 +224,11 @@ public final class PlainSocketImpl extends SocketImpl */ protected synchronized void create(boolean stream) throws IOException { - VMPlainSocketImpl.create(this); + channel = new SocketChannelImpl(false); + VMChannel vmchannel = channel.getVMChannel(); + vmchannel.initSocket(stream); + channel.configureBlocking(true); + impl.getState().setChannelFD(vmchannel.getState()); } /** @@ -222,7 +255,7 @@ public final class PlainSocketImpl extends SocketImpl */ protected void connect(InetAddress addr, int port) throws IOException { - VMPlainSocketImpl.connect(this, addr, port); + connect(new InetSocketAddress(addr, port), 0); } /** @@ -236,7 +269,14 @@ public final class PlainSocketImpl extends SocketImpl protected synchronized void connect(SocketAddress address, int timeout) throws IOException { - VMPlainSocketImpl.connect(this, address, timeout); + if (channel == null) + create(true); + boolean connected = channel.connect(address, timeout); + if (!connected) + throw new SocketTimeoutException("connect timed out"); + InetSocketAddress addr = channel.getVMChannel().getPeerAddress(); + this.address = addr.getAddress(); + this.port = addr.getPort(); } /** @@ -251,7 +291,10 @@ public final class PlainSocketImpl extends SocketImpl protected synchronized void bind(InetAddress addr, int port) throws IOException { - VMPlainSocketImpl.bind(this, addr, port); + if (channel == null) + create(true); + impl.bind(new InetSocketAddress(addr, port)); + localport = channel.getVMChannel().getLocalAddress().getPort(); } /** @@ -267,7 +310,7 @@ public final class PlainSocketImpl extends SocketImpl protected synchronized void listen(int queuelen) throws IOException { - VMPlainSocketImpl.listen(this, queuelen); + impl.listen(queuelen); } /** @@ -279,7 +322,16 @@ public final class PlainSocketImpl extends SocketImpl protected synchronized void accept(SocketImpl impl) throws IOException { - VMPlainSocketImpl.accept(this, impl); + if (channel == null) + create(true); + if (!(impl instanceof PlainSocketImpl)) + throw new IOException("incompatible SocketImpl: " + + impl.getClass().getName()); + PlainSocketImpl that = (PlainSocketImpl) impl; + VMChannel c = channel.getVMChannel().accept(); + that.impl.getState().setChannelFD(c.getState()); + that.channel = new SocketChannelImpl(c); + that.setOption(SO_REUSEADDR, Boolean.TRUE); } /** @@ -292,7 +344,9 @@ public final class PlainSocketImpl extends SocketImpl */ protected int available() throws IOException { - return VMPlainSocketImpl.available(this); + if (channel == null) + throw new SocketException("not connected"); + return channel.getVMChannel().available(); } /** @@ -308,65 +362,13 @@ public final class PlainSocketImpl extends SocketImpl */ protected void close() throws IOException { - VMPlainSocketImpl.close(this); - } - - public void sendUrgentData(int data) - { - VMPlainSocketImpl.sendUrgendData(this, data); - } - - /** - * Internal method used by SocketInputStream for reading data from - * the connection. Reads up to len bytes of data into the buffer - * buf starting at offset bytes into the buffer. - * - * @return the actual number of bytes read or -1 if end of stream. - * - * @throws IOException if an error occurs - */ - protected int read(byte[] buf, int offset, int len) - throws IOException - { - return VMPlainSocketImpl.read(this, buf, offset, len); + if (impl.getState().isValid()) + impl.close(); } - /** - * Internal method used by SocketInputStream for reading data from - * the connection. Reads and returns one byte of data. - * - * @return the read byte - * - * @throws IOException if an error occurs - */ - protected int read() - throws IOException + public void sendUrgentData(int data) throws IOException { - return VMPlainSocketImpl.read(this); - } - - /** - * Internal method used by SocketOuputStream for writing data to - * the connection. Writes up to len bytes of data from the buffer - * buf starting at offset bytes into the buffer. - * - * @throws IOException If an error occurs - */ - protected void write(byte[] buf, int offset, int len) - throws IOException - { - VMPlainSocketImpl.write(this, buf, offset, len); - } - - /** - * Internal method used by SocketOuputStream for writing data to - * the connection. Writes up one byte to the socket. - * - * @throws IOException If an error occurs - */ - protected void write(int data) throws IOException - { - VMPlainSocketImpl.write(this, data); + impl.sendUrgentData(data); } /** @@ -400,6 +402,87 @@ public final class PlainSocketImpl extends SocketImpl return out; } + + public VMChannel getVMChannel() + { + if (channel == null) + return null; + return channel.getVMChannel(); + } + + /* (non-Javadoc) + * @see java.net.SocketImpl#getInetAddress() + */ + protected InetAddress getInetAddress() + { + if (channel == null) + return null; + try + { + InetSocketAddress remote = channel.getVMChannel().getPeerAddress(); + if (remote == null) + return null; + return remote.getAddress(); + } + catch (IOException ioe) + { + return null; + } + } + + /* (non-Javadoc) + * @see java.net.SocketImpl#getLocalPort() + */ + protected int getLocalPort() + { + if (channel == null) + return -1; + try + { + InetSocketAddress local = channel.getVMChannel().getLocalAddress(); + if (local == null) + return -1; + return local.getPort(); + } + catch (IOException ioe) + { + return -1; + } + } + + public InetSocketAddress getLocalAddress() + { + if (channel == null) + return null; + try + { + return channel.getVMChannel().getLocalAddress(); + } + catch (IOException ioe) + { + return null; + } + } + + /* (non-Javadoc) + * @see java.net.SocketImpl#getPort() + */ + protected int getPort() + { + if (channel == null) + return -1; + try + { + InetSocketAddress remote = channel.getVMChannel().getPeerAddress(); + if (remote == null) + return -1; + return remote.getPort(); + } + catch (IOException ioe) + { + return -1; + } + } /** * This class contains an implementation of <code>InputStream</code> for @@ -437,7 +520,23 @@ public final class PlainSocketImpl extends SocketImpl */ public int read() throws IOException { - return PlainSocketImpl.this.read(); + if (channel == null) + throw new SocketException("not connected"); + while (true) + { + try + { + return channel.getVMChannel().read(); + } + catch (SocketTimeoutException ste) + { + throw ste; + } + catch (InterruptedIOException iioe) + { + // Ignore; NIO may throw this; net io shouldn't + } + } } /** @@ -454,12 +553,24 @@ public final class PlainSocketImpl extends SocketImpl */ public int read (byte[] buf, int offset, int len) throws IOException { - int bytes_read = PlainSocketImpl.this.read (buf, offset, len); - - if (bytes_read == 0) - return -1; - - return bytes_read; + if (channel == null) + throw new SocketException("not connected"); + ByteBuffer b = ByteBuffer.wrap(buf, offset, len); + while (true) + { + try + { + return channel.read(b); + } + catch (SocketTimeoutException ste) + { + throw ste; + } + catch (InterruptedIOException iioe) + { + // Ignored; NIO may throw this; net IO not. + } + } } } @@ -495,7 +606,20 @@ public final class PlainSocketImpl extends SocketImpl */ public void write(int b) throws IOException { - PlainSocketImpl.this.write(b); + if (channel == null) + throw new SocketException("not connected"); + while (true) + { + try + { + channel.getVMChannel().write(b); + return; + } + catch (InterruptedIOException iioe) + { + // Ignored. + } + } } /** @@ -510,7 +634,21 @@ public final class PlainSocketImpl extends SocketImpl */ public void write (byte[] buf, int offset, int len) throws IOException { - PlainSocketImpl.this.write (buf, offset, len); + if (channel == null) + throw new SocketException("not connected"); + ByteBuffer b = ByteBuffer.wrap(buf, offset, len); + while (b.hasRemaining()) + { + try + { + if (channel.write(b) == -1) + throw new IOException("channel has been closed"); + } + catch (InterruptedIOException iioe) + { + // Ignored. + } + } } } } |