Index: E:/projects/clear/eclipse/workspace/luni/META-INF/MANIFEST.MF
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/META-INF/MANIFEST.MF (revision 386513)
+++ E:/projects/clear/eclipse/workspace/luni/META-INF/MANIFEST.MF (working copy)
@@ -21,6 +21,7 @@
java.lang.reflect,
java.net,
java.util,
- org.apache.harmony.luni.util,
- org.apache.harmony.luni.platform
+ org.apache.harmony.luni.net,
+ org.apache.harmony.luni.platform,
+ org.apache.harmony.luni.util
Index: E:/projects/clear/eclipse/workspace/luni/.classpath
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/.classpath (revision 386513)
+++ E:/projects/clear/eclipse/workspace/luni/.classpath (working copy)
@@ -1,9 +1,14 @@
-
-
+
+
+
+
+
-
+
+
+
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/ServerSocket.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/ServerSocket.java (revision 386513)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/ServerSocket.java (working copy)
@@ -15,9 +15,10 @@
package java.net;
-
import java.io.IOException;
+import org.apache.harmony.luni.net.SocketImplProvider;
+
import com.ibm.oti.util.Msg;
/**
@@ -30,452 +31,472 @@
*/
public class ServerSocket {
- SocketImpl impl;
+ SocketImpl impl;
- static SocketImplFactory factory;
+ static SocketImplFactory factory;
- private volatile boolean isCreated = false;
+ private volatile boolean isCreated = false;
- private boolean isBound = false;
+ private boolean isBound = false;
- private boolean isClosed = false;
+ private boolean isClosed = false;
- /**
- * Construct a ServerSocket, which is not bound to any port. The default
- * number of pending connections may be backlogged.
- *
- * @see Socket
- */
- public ServerSocket() throws IOException {
- impl = factory != null ? factory.createSocketImpl()
- : new PlainServerSocketImpl();
- }
+ /**
+ * Construct a ServerSocket, which is not bound to any port. The default
+ * number of pending connections may be backlogged.
+ *
+ * @see Socket
+ */
+ public ServerSocket() throws IOException {
+ impl = factory != null ? factory.createSocketImpl()
+ :SocketImplProvider.getServerSocketImpl();
+ }
+
+ protected ServerSocket(SocketImpl impl){
+ this.impl = impl;
+ }
- /**
- * Construct a ServerSocket, bound to the nominated port on the default
- * localhost. The default number of pending connections may be backlogged.
- *
- * @param aport
- * the port number to listen for connection requests on
- * @see Socket
- */
- public ServerSocket(int aport) throws IOException {
- this(aport, defaultBacklog(), InetAddress.ANY);
- }
+ /**
+ * Construct a ServerSocket, bound to the nominated port on the default
+ * localhost. The default number of pending connections may be backlogged.
+ *
+ * @param aport
+ * the port number to listen for connection requests on
+ * @see Socket
+ */
+ public ServerSocket(int aport) throws IOException {
+ this(aport, defaultBacklog(), InetAddress.ANY);
+ }
- /**
- * Construct a ServerSocket, bound to the nominated port on the default
- * localhost. The number of pending connections that may be backlogged is a
- * specified.
- *
- * @param aport
- * the port number to listen for connection requests on
- * @param backlog
- * the number of pending connection requests, before requests are
- * rejected
- * @see Socket
- */
- public ServerSocket(int aport, int backlog) throws IOException {
- this(aport, backlog, InetAddress.ANY);
- }
+ /**
+ * Construct a ServerSocket, bound to the nominated port on the default
+ * localhost. The number of pending connections that may be backlogged is a
+ * specified.
+ *
+ * @param aport
+ * the port number to listen for connection requests on
+ * @param backlog
+ * the number of pending connection requests, before requests are
+ * rejected
+ * @see Socket
+ */
+ public ServerSocket(int aport, int backlog) throws IOException {
+ this(aport, backlog, InetAddress.ANY);
+ }
- /**
- * Construct a ServerSocket, bound to the nominated local host/port. The
- * number of pending connections that may be backlogged is a specified.
- *
- * @param aport
- * the port number to listen for connection requests on
- * @param localAddr
- * the local machine address to bind on
- * @param backlog
- * the number of pending connection requests, before requests are
- * rejected
- * @see Socket
- */
- public ServerSocket(int aport, int backlog, InetAddress localAddr)
- throws IOException {
- super();
- checkListen(aport);
- impl = factory != null ? factory.createSocketImpl()
- : new PlainServerSocketImpl();
- InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr;
+ /**
+ * Construct a ServerSocket, bound to the nominated local host/port. The
+ * number of pending connections that may be backlogged is a specified.
+ *
+ * @param aport
+ * the port number to listen for connection requests on
+ * @param localAddr
+ * the local machine address to bind on
+ * @param backlog
+ * the number of pending connection requests, before requests are
+ * rejected
+ * @see Socket
+ */
+ public ServerSocket(int aport, int backlog, InetAddress localAddr)
+ throws IOException {
+ super();
+ checkListen(aport);
+ impl = factory != null ? factory.createSocketImpl()
+ : SocketImplProvider.getServerSocketImpl();
+ InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr;
- synchronized (this) {
- impl.create(true);
- isCreated = true;
- try {
- impl.bind(addr, aport);
- isBound = true;
- impl.listen(backlog > 0 ? backlog : defaultBacklog());
- } catch (IOException e) {
- close();
- throw e;
- }
- }
- }
+ synchronized (this) {
+ impl.create(true);
+ isCreated = true;
+ try {
+ impl.bind(addr, aport);
+ isBound = true;
+ impl.listen(backlog > 0 ? backlog : defaultBacklog());
+ } catch (IOException e) {
+ close();
+ throw e;
+ }
+ }
+ }
- /**
- * Retrieve the first connection request and answer the 'host' socket that
- * will conduct further communications with the requesting 'client' socket.
- *
- * @return Socket the 'host' socket
- * @exception IOException
- * if an error occurs while instantiating the 'host' socket
- */
- public Socket accept() throws IOException {
- checkClosedAndCreate(false);
- if (!isBound())
- throw new SocketException(Msg.getString("K031f"));
+ /**
+ * Retrieve the first connection request and answer the 'host' socket that
+ * will conduct further communications with the requesting 'client' socket.
+ *
+ * @return Socket the 'host' socket
+ * @exception IOException
+ * if an error occurs while instantiating the 'host' socket
+ */
+ public Socket accept() throws IOException {
+ checkClosedAndCreate(false);
+ if (!isBound())
+ throw new SocketException(Msg.getString("K031f"));
- // If a SOCKS proxy is being used, accept does strange things.
- // Instead of returning a new Socket and allowing this ServerSocket
- // to be used for another accept, it actually uses the current
- // ServerSocket
- // as the accepted Socket. So, closing the returned socket will close
- // the
- // ServerSocket as well. The ServerSocket cannot be used for a second
- // accept.
- if (PlainSocketImpl.usingSocks()) {
- if (impl instanceof PlainSocketImpl) {
- try {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkAccept(getInetAddress().getHostName(),
- getLocalPort());
- }
- } catch (SecurityException e) {
- close();
- throw e;
- }
+ // If a SOCKS proxy is being used, accept does strange things.
+ // Instead of returning a new Socket and allowing this ServerSocket
+ // to be used for another accept, it actually uses the current
+ // ServerSocket
+ // as the accepted Socket. So, closing the returned socket will close
+ // the
+ // ServerSocket as well. The ServerSocket cannot be used for a second
+ // accept.
+ //FIXME: paulex comment this for compile
+// if (IOUtil.usingSocks()) {
+// if (impl instanceof PlainSocketImpl) {
+// try {
+// SecurityManager security = System.getSecurityManager();
+// if (security != null) {
+// security.checkAccept(getInetAddress().getHostAddress(),
+// getLocalPort());
+// }
+// } catch (SecurityException e) {
+// close();
+// throw e;
+// }
+//
+// ((PlainSocketImpl) impl).socksAccept();
+// return new Socket(impl);
+// }
+//
+// throw new IOException(Msg.getString("K0041")); //$NON-NLS-1$
+// }
- ((PlainSocketImpl) impl).socksAccept();
- return new Socket(impl);
- }
+ Socket aSocket = new Socket();
+ try {
+ synchronized (this) {
+ implAccept(aSocket);
+ }
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkAccept(aSocket.getInetAddress().getHostAddress(),
+ aSocket.getPort());
+ }
+ } catch (SecurityException e) {
+ aSocket.close();
+ throw e;
+ } catch (IOException e) {
+ aSocket.close();
+ throw e;
+ }
+ return aSocket;
+ }
- throw new IOException(Msg.getString("K0041")); //$NON-NLS-1$
- }
+ /**
+ * Check whether the server may listen for connection requests on
+ * aport. Throw an exception if the port is outside the
+ * valid range or does not satisfy the security policy.
+ *
+ * @param aPort
+ * the candidate port to listen on
+ */
+ void checkListen(int aPort) {
+ if (aPort < 0 || aPort > 65535)
+ throw new IllegalArgumentException(Msg.getString("K0325", aPort)); //$NON-NLS-1$
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkListen(aPort);
+ }
- Socket aSocket = new Socket();
- try {
- synchronized (this) {
- implAccept(aSocket);
- }
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkAccept(aSocket.getInetAddress().getHostName(),
- aSocket.getPort());
- }
- } catch (SecurityException e) {
- aSocket.close();
- throw e;
- } catch (IOException e) {
- aSocket.close();
- throw e;
- }
- return aSocket;
- }
+ /**
+ * Close this server socket. Any attempt to connect to this socket
+ * thereafter will fail.
+ */
+ public void close() throws IOException {
+ isClosed = true;
+ impl.close();
+ }
- /**
- * Check whether the server may listen for connection requests on
- * aport. Throw an exception if the port is outside the
- * valid range or does not satisfy the security policy.
- *
- * @param aPort
- * the candidate port to listen on
- */
- void checkListen(int aPort) {
- if (aPort < 0 || aPort > 65535)
- throw new IllegalArgumentException(Msg.getString("K0325", aPort)); //$NON-NLS-1$
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkListen(aPort);
- }
+ /**
+ * Answer the default number of pending connections on a server socket.
+ *
+ * @return int the default number of pending connection requests
+ */
+ static int defaultBacklog() {
+ return 50;
+ }
- /**
- * Close this server socket. Any attempt to connect to this socket
- * thereafter will fail.
- */
- public void close() throws IOException {
- isClosed = true;
- impl.close();
- }
+ /**
+ * Answer the local IP address for this server socket. Return null if the
+ * socket is not bound. This is useful on multihomed hosts.
+ *
+ * @return InetAddress the local address
+ */
+ public InetAddress getInetAddress() {
+ if (!isBound())
+ return null;
+ return impl.getInetAddress();
+ }
- /**
- * Answer the default number of pending connections on a server socket.
- *
- * @return int the default number of pending connection requests
- */
- static int defaultBacklog() {
- return 50;
- }
+ /**
+ * Answer the local port for this server socket. Return -1 if the socket is
+ * not bound.
+ *
+ * @return int the local port the server is listening on
+ */
+ public int getLocalPort() {
+ if (!isBound())
+ return -1;
+ return impl.getLocalPort();
+ }
- /**
- * Answer the local IP address for this server socket. Return null if the
- * socket is not bound. This is useful on multihomed hosts.
- *
- * @return InetAddress the local address
- */
- public InetAddress getInetAddress() {
- if (!isBound())
- return null;
- return impl.getInetAddress();
- }
+ /**
+ * Answer the time-out period of this server socket. This is the time the
+ * server will wait listening for connections, before exiting.
+ *
+ * @return int the listening timeout
+ * @exception SocketException
+ * thrown if option cannot be retrieved
+ */
+ public synchronized int getSoTimeout() throws IOException {
+ // TODO Bug-Reporter:check changed! checkClosedAndCreate(true);
+ if (!isCreated) {
+ synchronized (this) {
+ if (!isCreated) {
- /**
- * Answer the local port for this server socket. Return -1 if the socket is
- * not bound.
- *
- * @return int the local port the server is listening on
- */
- public int getLocalPort() {
- if (!isBound())
- return -1;
- return impl.getLocalPort();
- }
+ try {
+ impl.create(true);
+ } catch (SocketException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new SocketException(e.toString());
+ }
+ isCreated = true;
+ }
+ }
+ }
+ return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
+ }
- /**
- * Answer the time-out period of this server socket. This is the time the
- * server will wait listening for connections, before exiting.
- *
- * @return int the listening timeout
- * @exception SocketException
- * thrown if option cannot be retrieved
- */
- public synchronized int getSoTimeout() throws IOException {
- checkClosedAndCreate(true);
- return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
- }
+ /**
+ * Invoke the server socket implementation to accept a connection on the
+ * newly created aSocket.
+ *
+ * @param aSocket
+ * the concrete socketImpl to accept the connection request on
+ * @exception IOException
+ * thrown if connection cannot be accepted
+ */
+ protected final void implAccept(Socket aSocket) throws IOException {
+ impl.accept(aSocket.impl);
+ aSocket.accepted();
+ }
- /**
- * Invoke the server socket implementation to accept a connection on the
- * newly created aSocket.
- *
- * @param aSocket
- * the concrete socketImpl to accept the connection request on
- * @exception IOException
- * thrown if connection cannot be accepted
- */
- protected final void implAccept(Socket aSocket) throws IOException {
- impl.accept(aSocket.impl);
- aSocket.accepted();
- }
+ /**
+ * Set the server socket implementation factory. This method may only be
+ * invoked with sufficient security and only once during the application
+ * lifetime.
+ *
+ * @param aFactory
+ * the streaming socket factory to be used for further socket
+ * instantiations
+ * @exception IOException
+ * thrown if the factory is already set
+ */
+ public static synchronized void setSocketFactory(SocketImplFactory aFactory)
+ throws IOException {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkSetFactory();
+ if (factory == null)
+ factory = aFactory;
+ else
+ throw new SocketException(Msg.getString("K0042")); //$NON-NLS-1$
+ }
- /**
- * Set the server socket implementation factory. This method may only be
- * invoked with sufficient security and only once during the application
- * lifetime.
- *
- * @param aFactory
- * the streaming socket factory to be used for further socket
- * instantiations
- * @exception IOException
- * thrown if the factory is already set
- */
- public static synchronized void setSocketFactory(SocketImplFactory aFactory)
- throws IOException {
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkSetFactory();
- if (factory == null)
- factory = aFactory;
- else
- throw new SocketException(Msg.getString("K0042")); //$NON-NLS-1$
- }
+ /**
+ * Set the listen time-out period for this server socket.
+ *
+ * @param timeout
+ * the time to wait for a connection request
+ * @exception SocketException
+ * thrown if an error occurs during setting the option
+ */
+ public synchronized void setSoTimeout(int timeout) throws SocketException {
+ checkClosedAndCreate(true);
+ if (timeout >= 0) {
+ impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+ } else {
+ throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
+ }
+ }
- /**
- * Set the listen time-out period for this server socket.
- *
- * @param timeout
- * the time to wait for a connection request
- * @exception SocketException
- * thrown if an error occurs during setting the option
- */
- public synchronized void setSoTimeout(int timeout) throws SocketException {
- checkClosedAndCreate(true);
- if (timeout >= 0) {
- impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
- } else {
- throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
- }
- }
+ /**
+ * Answers a string containing a concise, human-readable description of the
+ * server socket. The port field is reported a zero, as there
+ * is no connection formed to the server.
+ *
+ * @return String the description
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer(64);
+ result.append("ServerSocket["); //$NON-NLS-1$
+ if (!isBound())
+ return result.append("unbound]").toString(); //$NON-NLS-1$
+ return result.append("addr="). //$NON-NLS-1$
+ append(getInetAddress()).append(",port=0,localport="). //$NON-NLS-1$
+ append(getLocalPort()).append("]"). //$NON-NLS-1$
+ toString();
+ }
- /**
- * Answers a string containing a concise, human-readable description of the
- * server socket. The port field is reported a zero, as there
- * is no connection formed to the server.
- *
- * @return String the description
- */
- public String toString() {
- StringBuffer result = new StringBuffer(64);
- result.append("ServerSocket["); //$NON-NLS-1$
- if (!isBound())
- return result.append("unbound]").toString(); //$NON-NLS-1$
- return result.append("addr="). //$NON-NLS-1$
- append(getInetAddress()).append(",port=0,localport="). //$NON-NLS-1$
- append(getLocalPort()).append("]"). //$NON-NLS-1$
- toString();
- }
+ /**
+ * Bind the ServerSocket to the nominated local host/port. The default
+ * number of pending connections may be backlogged.
+ *
+ * @param localAddr
+ * the local machine address and port to bind on
+ *
+ * @exception IllegalArgumentException
+ * if the SocketAddress is not supported
+ * @exception IOException
+ * if the socket is already bound, or a problem occurs during
+ * the bind
+ */
+ public void bind(SocketAddress localAddr) throws IOException {
+ bind(localAddr, defaultBacklog());
+ }
- /**
- * Bind the ServerSocket to the nominated local host/port. The default
- * number of pending connections may be backlogged.
- *
- * @param localAddr
- * the local machine address and port to bind on
- *
- * @exception IllegalArgumentException
- * if the SocketAddress is not supported
- * @exception IOException
- * if the socket is already bound, or a problem occurs during
- * the bind
- */
- public void bind(SocketAddress localAddr) throws IOException {
- bind(localAddr, defaultBacklog());
- }
+ /**
+ * Bind the ServerSocket to the nominated local host/port. The number of
+ * pending connections that may be backlogged is a specified.
+ *
+ * @param localAddr
+ * the local machine address and port to bind on
+ * @param backlog
+ * the number of pending connection requests, before requests are
+ * rejected
+ *
+ * @exception IllegalArgumentException
+ * if the SocketAddress is not supported
+ * @exception IOException
+ * if the socket is already bound, or a problem occurs during
+ * the bind
+ */
+ public void bind(SocketAddress localAddr, int backlog) throws IOException {
+ checkClosedAndCreate(true);
+ if (isBound())
+ throw new BindException(Msg.getString("K0315")); //$NON-NLS-1$
+ int port = 0;
+ InetAddress addr = InetAddress.ANY;
+ if (localAddr != null) {
+ if (!(localAddr instanceof InetSocketAddress))
+ throw new IllegalArgumentException(Msg.getString(
+ "K0316", localAddr.getClass())); //$NON-NLS-1$
+ InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
+ if ((addr = inetAddr.getAddress()) == null)
+ throw new SocketException(Msg.getString(
+ "K0317", inetAddr.getHostName())); //$NON-NLS-1$
+ port = inetAddr.getPort();
+ }
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkListen(port);
- /**
- * Bind the ServerSocket to the nominated local host/port. The number of
- * pending connections that may be backlogged is a specified.
- *
- * @param localAddr
- * the local machine address and port to bind on
- * @param backlog
- * the number of pending connection requests, before requests are
- * rejected
- *
- * @exception IllegalArgumentException
- * if the SocketAddress is not supported
- * @exception IOException
- * if the socket is already bound, or a problem occurs during
- * the bind
- */
- public void bind(SocketAddress localAddr, int backlog) throws IOException {
- checkClosedAndCreate(true);
- if (isBound())
- throw new BindException(Msg.getString("K0315")); //$NON-NLS-1$
- int port = 0;
- InetAddress addr = InetAddress.ANY;
- if (localAddr != null) {
- if (!(localAddr instanceof InetSocketAddress))
- throw new IllegalArgumentException(Msg.getString(
- "K0316", localAddr.getClass())); //$NON-NLS-1$
- InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
- if ((addr = inetAddr.getAddress()) == null)
- throw new SocketException(Msg.getString(
- "K0317", inetAddr.getHostName())); //$NON-NLS-1$
- port = inetAddr.getPort();
- }
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkListen(port);
+ synchronized (this) {
+ try {
+ impl.bind(addr, port);
+ isBound = true;
+ impl.listen(backlog > 0 ? backlog : defaultBacklog());
+ } catch (IOException e) {
+ close();
+ throw e;
+ }
+ }
+ }
- synchronized (this) {
- try {
- impl.bind(addr, port);
- isBound = true;
- impl.listen(backlog > 0 ? backlog : defaultBacklog());
- } catch (IOException e) {
- close();
- throw e;
- }
- }
- }
+ /**
+ * Answer the local SocketAddress for this server socket, or null if the
+ * socket is not bound. This is useful on multihomed hosts.
+ */
+ public SocketAddress getLocalSocketAddress() {
+ if (!isBound())
+ return null;
+ return new InetSocketAddress(getInetAddress(), getLocalPort());
+ }
- /**
- * Answer the local SocketAddress for this server socket, or null if the
- * socket is not bound. This is useful on multihomed hosts.
- */
- public SocketAddress getLocalSocketAddress() {
- if (!isBound())
- return null;
- return new InetSocketAddress(getInetAddress(), getLocalPort());
- }
+ /**
+ * Return if the server socket is bound to a local address and port.
+ */
+ public boolean isBound() {
+ return isBound;
+ }
- /**
- * Return if the server socket is bound to a local address and port.
- */
- public boolean isBound() {
- return isBound;
- }
+ /**
+ * Return if the server socket is closed.
+ */
+ public boolean isClosed() {
+ return isClosed;
+ }
- /**
- * Return if the server socket is closed.
- */
- public boolean isClosed() {
- return isClosed;
- }
+ /**
+ * Check if the socket is closed, and throw an exception.
+ */
+ private void checkClosedAndCreate(boolean create) throws SocketException {
+ if (isClosed())
+ throw new SocketException(Msg.getString("K003d"));
- /**
- * Check if the socket is closed, and throw an exception.
- */
- private void checkClosedAndCreate(boolean create) throws SocketException {
- if (isClosed())
- throw new SocketException(Msg.getString("K003d"));
+ if (!create || isCreated)
+ return;
- if (!create || isCreated)
- return;
+ synchronized (this) {
+ if (isCreated)
+ return;
+ try {
+ impl.create(true);
+ } catch (SocketException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new SocketException(e.toString());
+ }
+ isCreated = true;
+ }
+ }
- synchronized (this) {
- if (isCreated)
- return;
- try {
- impl.create(true);
- } catch (SocketException e) {
- throw e;
- } catch (IOException e) {
- throw new SocketException(e.toString());
- }
- isCreated = true;
- }
- }
+ /**
+ * Set the SO_REUSEADDR socket option.
+ *
+ * @param reuse
+ * the socket SO_REUSEADDR option setting
+ */
+ public void setReuseAddress(boolean reuse) throws SocketException {
+ checkClosedAndCreate(true);
+ impl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
+ : Boolean.FALSE);
+ }
- /**
- * Set the SO_REUSEADDR socket option.
- *
- * @param reuse
- * the socket SO_REUSEADDR option setting
- */
- public void setReuseAddress(boolean reuse) throws SocketException {
- checkClosedAndCreate(true);
- impl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
- : Boolean.FALSE);
- }
+ /**
+ * Get the state of the SO_REUSEADDR socket option.
+ */
+ public boolean getReuseAddress() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR))
+ .booleanValue();
+ }
- /**
- * Get the state of the SO_REUSEADDR socket option.
- */
- public boolean getReuseAddress() throws SocketException {
- checkClosedAndCreate(true);
- return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR))
- .booleanValue();
- }
+ /**
+ * Set the socket receive buffer size.
+ *
+ * @param size
+ * the buffer size, in bytes
+ *
+ * @exception java.net.SocketException
+ * If an error occurs while setting the size or the size is
+ * invalid.
+ */
+ public void setReceiveBufferSize(int size) throws SocketException {
+ checkClosedAndCreate(true);
+ if (size >= 1)
+ impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+ else
+ throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
+ }
- /**
- * Set the socket receive buffer size.
- *
- * @param size
- * the buffer size, in bytes
- *
- * @exception java.net.SocketException
- * If an error occurs while setting the size or the size is
- * invalid.
- */
- public void setReceiveBufferSize(int size) throws SocketException {
- checkClosedAndCreate(true);
- if (size >= 1)
- impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
- else
- throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
- }
-
- /**
- * Answer the socket receive buffer size (SO_RCVBUF).
- *
- * @return int socket receive buffer size
- */
- public int getReceiveBufferSize() throws SocketException {
- checkClosedAndCreate(true);
- return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
- }
+ /**
+ * Answer the socket receive buffer size (SO_RCVBUF).
+ *
+ * @return int socket receive buffer size
+ */
+ public int getReceiveBufferSize() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
+ }
}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/DatagramSocketImpl.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/DatagramSocketImpl.java (revision 386513)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/java/net/DatagramSocketImpl.java (working copy)
@@ -19,6 +19,10 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+
/**
* The abstract superclass of datagram & multicast socket implementatations.
*/
@@ -79,8 +83,9 @@
*
* @return InetAddress the local address to which the socket is bound.
*/
- abstract InetAddress getLocalAddress();
-
+ InetAddress getLocalAddress() {
+ return Platform.getNetworkSystem().getSocketLocalAddress(fd, NetUtil.preferIPv6Addresses());
+ }
/**
* Answer the local port. If the socket was bound to any available port, as
* flagged by a localPort value of -1, query the IP stack.
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java (revision 0)
@@ -0,0 +1,737 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketOptions;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.security.AccessController;
+
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+
+import com.ibm.oti.util.Msg;
+import com.ibm.oti.util.PriviAction;
+
+/**
+ * The default, concrete instance of datagram sockets. This class does not
+ * support security checks. Alternative types of DatagramSocketImpl's may be
+ * used by setting the impl.prefix system property.
+ */
+
+class PlainDatagramSocketImpl extends DatagramSocketImpl {
+
+ static final int MULTICAST_IF = 1;
+
+ static final int MULTICAST_TTL = 2;
+
+ static final int TCP_NODELAY = 4;
+
+ static final int FLAG_SHUTDOWN = 8;
+
+ private final static int SO_BROADCAST = 32;
+
+ final static int IP_MULTICAST_ADD = 19;
+
+ final static int IP_MULTICAST_DROP = 20;
+
+ final static int IP_MULTICAST_TTL = 17;
+
+ private boolean bindToDevice;
+
+ private byte[] ipaddress = { 0, 0, 0, 0 };
+
+ private int ttl = 1;
+
+ private INetworkSystem netImpl = Platform.getNetworkSystem();
+
+ private volatile boolean isNativeConnected = false;
+
+ public int receiveTimeout = 0;
+
+ public boolean streaming = true;
+
+ public boolean shutdownInput = false;
+
+ // for datagram and multicast sockets we have to set
+ // REUSEADDR and REUSEPORT when REUSEADDR is set
+ // for other types of sockets we need to just set REUSEADDR
+ // therefore we have this other option which sets
+ // both if supported by the platform.
+ // this cannot be in SOCKET_OPTIONS because since it
+ // is a public interface it ends up being public even
+ // if it is not declared public
+ static final int REUSEADDR_AND_REUSEPORT = 10001;
+
+ // used to keep address to which the socket was connected to at the
+ // native level
+ private InetAddress connectedAddress = null;
+
+ private int connectedPort = -1;
+
+ // used to store the trafficClass value which is simply returned
+ // as the value that was set. We also need it to pass it to methods
+ // that specify an address packets are going to be sent to
+ private int trafficClass = 0;
+
+ // Fill in the JNI id caches
+ // private static native void oneTimeInitialization(boolean
+ // jcl_IPv6_support);
+ //
+ // static {
+ // oneTimeInitialization(true);
+ // }
+
+
+ public PlainDatagramSocketImpl(FileDescriptor fd, int localPort) {
+ super();
+ this.fd = fd;
+ this.localPort = localPort;
+ }
+
+ public PlainDatagramSocketImpl(){
+ super();
+ }
+
+ /**
+ * Bind the datagram socket to the nominated localhost/port. Sockets must be
+ * bound prior to attempting to send or receive data.
+ *
+ * @param port
+ * the port on the localhost to bind
+ * @param addr
+ * the address on the multihomed localhost to bind
+ *
+ * @exception SocketException
+ * if an error occured during bind, such as if the port was
+ * already bound
+ */
+ public void bind(int port, InetAddress addr) throws SocketException {
+ String prop = (String) AccessController.doPrivileged(new PriviAction(
+ "bindToDevice"));
+ boolean useBindToDevice = prop != null
+ && prop.toLowerCase().equals("true");
+ bindToDevice = netImpl.bind2(fd, port, useBindToDevice, addr);
+ if (0 != port) {
+ localPort = port;
+ } else {
+ localPort = netImpl.getSocketLocalPort(fd,
+ NetUtil.preferIPv6Addresses());
+ }
+
+ try {
+ // Ignore failures
+ setOption(SO_BROADCAST, Boolean.TRUE);
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Close the socket.
+ */
+ public void close() {
+ synchronized (fd) {
+ if (fd.valid()) {
+ try {
+ netImpl.socketClose(fd);
+ } catch (IOException e) {
+ // TODO do nothing?
+ }
+ fd = new FileDescriptor();
+ }
+ }
+ }
+
+ /**
+ * Allocate the socket descriptor in the IP stack.
+ */
+ public void create() throws SocketException {
+ netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
+ }
+
+ protected void finalize() {
+ close();
+ }
+
+ /**
+ * Answer the nominated socket option. As the timeouts are not set as
+ * options in the IP stack, the field value is returned.
+ *
+ * @return Object the nominated socket option value
+ */
+ public Object getOption(int optID) throws SocketException {
+ if (optID == SocketOptions.SO_TIMEOUT) {
+ return new Integer(receiveTimeout);
+ } else if (optID == SocketOptions.IP_TOS) {
+ return new Integer(trafficClass);
+ } else {
+ // Call the native first so there will be
+ // an exception if the socket if closed.
+ Object result = netImpl.getSocketOption(fd, optID);
+ if (optID == SocketOptions.IP_MULTICAST_IF
+ && (netImpl.getSocketFlags() & MULTICAST_IF) != 0) {
+ try {
+ return Inet4Address.getByAddress(ipaddress);
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+ return result;
+ }
+ }
+
+ public int getTimeToLive() throws IOException {
+ // Call the native first so there will be an exception if the socket if
+ // closed.
+ int result = (((Byte) getOption(IP_MULTICAST_TTL)).byteValue()) & 0xFF;
+ if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
+ return ttl;
+ }
+ return result;
+ }
+
+ public byte getTTL() throws IOException {
+ // Call the native first so there will be an exception if the socket if
+ // closed.
+ byte result = ((Byte) getOption(IP_MULTICAST_TTL)).byteValue();
+ if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
+ return (byte) ttl;
+ }
+ return result;
+ }
+
+ /**
+ * Add this socket to the multicast group. A socket must joint a group
+ * before data may be received. A socket may be a member of multiple groups
+ * but may join any group once.
+ *
+ * @param addr
+ * the multicast group to be joined
+ * @exception java.io.IOException
+ * may be thrown while joining a group
+ */
+ public void join(InetAddress addr) throws IOException {
+ setOption(IP_MULTICAST_ADD, new GenericIPMreq(addr));
+ }
+
+ /**
+ * Add this socket to the multicast group. A socket must join a group before
+ * data may be received. A socket may be a member of multiple groups but may
+ * join any group once.
+ *
+ * @param addr
+ * the multicast group to be joined
+ * @param netInterface
+ * the network interface on which the addresses should be dropped
+ * @exception java.io.IOException
+ * may be thrown while joining a group
+ */
+ public void joinGroup(SocketAddress addr, NetworkInterface netInterface)
+ throws IOException {
+ if (addr instanceof InetSocketAddress) {
+ InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
+ setOption(IP_MULTICAST_ADD, new GenericIPMreq(groupAddr,
+ netInterface));
+ }
+ }
+
+ /**
+ * Remove the socket from the multicast group.
+ *
+ * @param addr
+ * the multicast group to be left
+ * @exception java.io.IOException
+ * May be thrown while leaving the group
+ */
+ public void leave(InetAddress addr) throws IOException {
+ setOption(IP_MULTICAST_DROP, new GenericIPMreq(addr));
+ }
+
+ /**
+ * Remove the socket from the multicast group.
+ *
+ * @param addr
+ * the multicast group to be left
+ * @param netInterface
+ * the network interface on which the addresses should be dropped
+ * @exception java.io.IOException
+ * May be thrown while leaving the group
+ */
+ public void leaveGroup(SocketAddress addr, NetworkInterface netInterface)
+ throws IOException {
+ if (addr instanceof InetSocketAddress) {
+ InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
+ setOption(IP_MULTICAST_DROP, new GenericIPMreq(groupAddr,
+ netInterface));
+ }
+ }
+
+ // /**
+ // * Connect the socket to a port and address
+ // *
+ // * @param aFD
+ // * the FileDescriptor to associate with the socket
+ // * @param port
+ // * the port to connect to
+ // * @param trafficClass
+ // * the traffic Class to be used then the connection is made
+ // * @param inetAddress
+ // * address to connect to.
+ // *
+ // * @exception SocketException
+ // * if the connect fails
+ // */
+ // protected static native void connectDatagramImpl2(FileDescriptor aFD,
+ // int port, int trafficClass, InetAddress inetAddress)
+ // throws SocketException;
+ //
+ // /**
+ // * Disconnect the socket to a port and address
+ // *
+ // * @param aFD
+ // * the FileDescriptor to associate with the socket
+ // *
+ // * @exception SocketException
+ // * if the disconnect fails
+ // */
+ // protected static native void disconnectDatagramImpl(FileDescriptor aFD)
+ // throws SocketException;
+ //
+ // /**
+ // * Allocate a datagram socket in the IP stack. The socket is associated
+ // with
+ // * the aFD.
+ // *
+ // * @param aFD
+ // * the FileDescriptor to associate with the socket
+ // * @param preferIPv4Stack
+ // * IP stack preference if underlying platform is V4/V6
+ // * @exception SocketException
+ // * upon an allocation error
+ // */
+ // protected static native void createDatagramSocketImpl(FileDescriptor aFD,
+ // boolean preferIPv4Stack) throws SocketException;
+ //
+ // /**
+ // * Bind the socket to the port/localhost in the IP stack.
+ // *
+ // * @param aFD
+ // * the socket descriptor
+ // * @param port
+ // * the option selector
+ // * @param bindToDevice
+ // * bind the socket to the specified interface
+ // * @param inetAddress
+ // * address to connect to.
+ // * @exception SocketException
+ // * thrown if bind operation fails
+ // */
+ // protected static native boolean socketBindImpl2(FileDescriptor aFD,
+ // int port, boolean bindToDevice, InetAddress inetAddress)
+ // throws SocketException;
+ //
+ // /**
+ // * Peek on the socket, update sender address and answer the
+ // * sender port.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @param sender
+ // * an InetAddress, to be updated with the sender's address
+ // * @param receiveTimeout
+ // * the maximum length of time the socket should block, reading
+ // * @return int the sender port
+ // *
+ // * @exception IOException
+ // * upon an read error or timeout
+ // */
+ // protected static native int peekDatagramImpl(FileDescriptor aFD,
+ // InetAddress sender, int receiveTimeout) throws IOException;
+ //
+ // /**
+ // * Recieve data on the socket into the specified buffer. The packet fields
+ // * data & length are passed in addition to
+ // * packet to eliminate the JNI field access calls.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @param packet
+ // * the DatagramPacket to receive into
+ // * @param data
+ // * the data buffer of the packet
+ // * @param offset
+ // * the offset in the data buffer
+ // * @param length
+ // * the length of the data buffer in the packet
+ // * @param receiveTimeout
+ // * the maximum length of time the socket should block, reading
+ // * @param peek
+ // * indicates to peek at the data
+ // * @exception IOException
+ // * upon an read error or timeout
+ // */
+ // protected static native int receiveDatagramImpl2(FileDescriptor aFD,
+ // DatagramPacket packet, byte[] data, int offset, int length,
+ // int receiveTimeout, boolean peek) throws IOException;
+ //
+ // /**
+ // * Recieve data on the connected socket into the specified buffer. The
+ // * packet fields data & length are passed in
+ // * addition to packet to eliminate the JNI field access
+ // * calls.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @param packet
+ // * the DatagramPacket to receive into
+ // * @param data
+ // * the data buffer of the packet
+ // * @param offset
+ // * the offset in the data buffer
+ // * @param length
+ // * the length of the data buffer in the packet
+ // * @param receiveTimeout
+ // * the maximum length of time the socket should block, reading
+ // * @param peek
+ // * indicates to peek at the data
+ // * @exception IOException
+ // * upon an read error or timeout
+ // */
+ // protected static native int recvConnectedDatagramImpl(FileDescriptor aFD,
+ // DatagramPacket packet, byte[] data, int offset, int length,
+ // int receiveTimeout, boolean peek) throws IOException;
+ //
+ // /**
+ // * Send the data to the nominated target address
+ // * and port. These values are derived from the
+ // * DatagramPacket to reduce the field calls within JNI.
+ // *
+ // * @param fd
+ // * the socket FileDescriptor
+ // * @param data
+ // * the data buffer of the packet
+ // * @param offset
+ // * the offset in the data buffer
+ // * @param length
+ // * the length of the data buffer in the packet
+ // * @param port
+ // * the target host port
+ // * @param trafficClass
+ // * the traffic class to be used when the datagram is sent
+ // * @param inetAddress
+ // * address to connect to.
+ // *
+ // * @exception IOException
+ // * upon an read error or timeout
+ // */
+ // protected static native int sendDatagramImpl2(FileDescriptor fd,
+ // byte[] data, int offset, int length, int port,
+ // boolean bindToDevice, int trafficClass, InetAddress inetAddress)
+ // throws IOException;
+ //
+ // /**
+ // * Send the data to the address and port to which the was
+ // * connnected and port.
+ // *
+ // * @param fd
+ // * the socket FileDescriptor
+ // * @param data
+ // * the data buffer of the packet
+ // * @param offset
+ // * the offset in the data buffer
+ // * @param length
+ // * the length of the data buffer in the packet
+ // * @param bindToDevice
+ // * not used, current kept in case needed as was the case for
+ // * sendDatagramImpl
+ // * @exception IOException
+ // * upon an read error or timeout
+ // */
+ // protected static native int sendConnectedDatagramImpl(FileDescriptor fd,
+ // byte[] data, int offset, int length, boolean bindToDevice)
+ // throws IOException;
+
+ protected int peek(InetAddress sender) throws IOException {
+ if (isNativeConnected) {
+ // in this case we know the port and address from which the data
+ // must have be been received as the socket is connected. However,
+ // we still need to do the receive in order to know that there was
+ // data received. We use a short buffer as we don't actually need
+ // the packet, only the knowledge that it is there
+ byte[] storageArray = new byte[10];
+ DatagramPacket pack = new DatagramPacket(storageArray,
+ storageArray.length);
+ netImpl.recvConnectedDatagram(fd, pack, pack.getData(), pack
+ .getOffset(), pack.getLength(), receiveTimeout, true); // peek
+ // to set the sender ,we now use a native function
+ // sender.ipaddress = connectedAddress.getAddress();
+ netImpl.setInetAddress(sender, connectedAddress.getAddress());
+ return connectedPort;
+ }
+ return netImpl.peekDatagram(fd, sender, receiveTimeout);
+ }
+
+ /**
+ * Answer the data that may be read at this socket. Any data larger than the
+ * packet buffer length will be discarded. The read will block until either
+ * data is is read or, if the timeout is defined, the operation times out.
+ *
+ * @exception IOException
+ * if an error or timeout occurs during a read
+ */
+ public void receive(DatagramPacket pack) throws java.io.IOException {
+ try {
+ if (isNativeConnected) {
+ // do not peek
+ netImpl.recvConnectedDatagram(fd, pack, pack.getData(),
+ pack.getOffset(), pack.getLength(), receiveTimeout,
+ false);
+ updatePacketRecvAddress(pack);
+ } else {
+ // receiveDatagramImpl2
+ netImpl.receiveDatagram(fd, pack, pack.getData(), pack
+ .getOffset(), pack.getLength(), receiveTimeout, false);
+ }
+ } catch (InterruptedIOException e) {
+ throw new SocketTimeoutException(e.getMessage());
+ }
+ }
+
+ /**
+ * Send the data on this socket.
+ *
+ * @exception IOException
+ * if an error occurs during the write
+ */
+ public void send(DatagramPacket packet) throws IOException {
+
+ if (isNativeConnected) {
+ netImpl.sendConnectedDatagram(fd, packet.getData(), packet
+ .getOffset(), packet.getLength(), bindToDevice);
+ } else {
+ // sendDatagramImpl2
+ netImpl.sendDatagram(fd, packet.getData(), packet.getOffset(),
+ packet.getLength(), packet.getPort(), bindToDevice,
+ trafficClass, packet.getAddress());
+ }
+ }
+
+ /**
+ * Set the nominated socket option. As the timeouts are not set as options
+ * in the IP stack, the value is stored in an instance field.
+ *
+ * @exception SocketException
+ * thrown if the option value is unsupported or invalid
+ */
+ public void setOption(int optID, Object val) throws SocketException {
+ // for datagram sockets on some platforms we have to set both the
+ // REUSEADDR AND REUSEPORT so for REUSEADDR set this option option
+ // which tells the VM to set the two values as appropriate for the
+ // platform
+ if (optID == SocketOptions.SO_REUSEADDR) {
+ optID = REUSEADDR_AND_REUSEPORT;
+ }
+
+ if (optID == SocketOptions.SO_TIMEOUT) {
+ receiveTimeout = ((Integer) val).intValue();
+ } else {
+ int flags = netImpl.getSocketFlags();
+ try {
+ netImpl.setSocketOption(fd, optID | (flags << 16), val);
+ } catch (SocketException e) {
+ // we don't throw an exception for IP_TOS even if the platform
+ // won't let us set the requested value
+ if (optID != SocketOptions.IP_TOS) {
+ throw e;
+ }
+ }
+ if (optID == SocketOptions.IP_MULTICAST_IF
+ && (flags & MULTICAST_IF) != 0) {
+ InetAddress inet = (InetAddress) val;
+ if (bytesToInt(inet.getAddress(), 0) == 0
+ || inet.isLoopbackAddress()) {
+ ipaddress = ((InetAddress) val).getAddress();
+ } else {
+ InetAddress local = null;
+ try {
+ local = InetAddress.getLocalHost();
+ } catch (UnknownHostException e) {
+ throw new SocketException("getLocalHost(): "
+ + e.toString());
+ }
+ if (inet.equals(local)) {
+ ipaddress = ((InetAddress) val).getAddress();
+ } else {
+ throw new SocketException(val + " != getLocalHost(): "
+ + local);
+ }
+ }
+ }
+ // save this value as it is acutally used differently for IPv4 and
+ // IPv6 so we cannot get the value using the getOption. The option
+ // is actually only set for IPv4 and a masked version of the value
+ // will be set as only a subset of the values are allowed on the
+ // socket. Therefore we need to retain it to return the value that
+ // was set. We also need the value to be passed into a number of
+ // natives so that it can be used properly with IPv6
+ if (optID == SocketOptions.IP_TOS) {
+ trafficClass = ((Integer) val).intValue();
+ }
+ }
+ }
+
+ public void setTimeToLive(int ttl) throws java.io.IOException {
+ setOption(IP_MULTICAST_TTL, new Byte((byte) (ttl & 0xFF)));
+ if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
+ this.ttl = ttl;
+ }
+ }
+
+ public void setTTL(byte ttl) throws java.io.IOException {
+ setOption(IP_MULTICAST_TTL, new Byte(ttl));
+ if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
+ this.ttl = ttl;
+ }
+ }
+
+ /**
+ * Connect the socket to the specified remote address and port.
+ *
+ * @param inetAddr
+ * the remote address
+ * @param port
+ * the remote port
+ *
+ * @exception SocketException
+ * possibly thrown, if the datagram socket cannot be
+ * connected to the specified remote address and port
+ */
+ public void connect(InetAddress inetAddr, int port) throws SocketException {
+
+ // connectDatagram impl2
+ netImpl.connectDatagram(fd, port, trafficClass, inetAddr);
+
+ // if we get here then we are connected at the native level
+ try {
+ connectedAddress = InetAddress.getByAddress(inetAddr.getAddress());
+ } catch (UnknownHostException e) {
+ // this is never expected to happen as we should not have gotten
+ // here if the address is not resolvable
+ throw new SocketException(Msg.getString(
+ "K0317", inetAddr.getHostName())); //$NON-NLS-1$
+ }
+ connectedPort = port;
+ isNativeConnected = true;
+ }
+
+ /**
+ * Disconnect the socket from the remote address and port.
+ */
+ public void disconnect() {
+ try {
+ netImpl.disconnectDatagram(fd);
+ } catch (Exception e) {
+ // there is currently no way to return an error so just eat any
+ // exception
+ }
+ connectedPort = -1;
+ connectedAddress = null;
+ isNativeConnected = false;
+ }
+
+ /**
+ * Receive data into the supplied datagram packet by peeking. The data is
+ * not removed and will be received by another peekData() or receive() call.
+ *
+ * This call will block until either data is received or, if a timeout is
+ * set, the timeout expires.
+ *
+ * @param pack
+ * the DatagramPacket used to store the data
+ *
+ * @return the port the packet was received from
+ *
+ * @exception IOException
+ * if an error occurs
+ */
+ public int peekData(DatagramPacket pack) throws IOException {
+ try {
+ if (isNativeConnected) {
+ netImpl.recvConnectedDatagram(fd, pack, pack.getData(),
+ pack.getOffset(), pack.getLength(), receiveTimeout,
+ true); // peek
+ updatePacketRecvAddress(pack);
+ } else {
+ // receiveDatagram 2
+ netImpl.receiveDatagram(fd, pack, pack.getData(), pack
+ .getOffset(), pack.getLength(), receiveTimeout, true); // peek
+ }
+ } catch (InterruptedIOException e) {
+ throw new SocketTimeoutException(e.getMessage());
+ }
+ return pack.getPort();
+ }
+
+ /**
+ * Set the received address and port in the packet. We do this when the
+ * Datagram socket is connected at the native level and the
+ * recvConnnectedDatagramImpl does not update the packet with address from
+ * which the packet was received
+ *
+ * @param packet
+ * the packet to be updated
+ */
+ private void updatePacketRecvAddress(DatagramPacket packet) {
+ packet.setAddress(connectedAddress);
+ packet.setPort(connectedPort);
+ }
+
+ static void intToBytes(int value, byte bytes[], int start) {
+ // Shift the int so the current byte is right-most
+ // Use a byte mask of 255 to single out the last byte.
+ bytes[start] = (byte) ((value >> 24) & 255);
+ bytes[start + 1] = (byte) ((value >> 16) & 255);
+ bytes[start + 2] = (byte) ((value >> 8) & 255);
+ bytes[start + 3] = (byte) (value & 255);
+ }
+
+ static int bytesToInt(byte bytes[], int start) {
+ // First mask the byte with 255, as when a negative
+ // signed byte converts to an integer, it has bits
+ // on in the first 3 bytes, we are only concerned
+ // about the right-most 8 bits.
+ // Then shift the rightmost byte to align with its
+ // position in the integer.
+ int value = ((bytes[start + 3] & 255))
+ | ((bytes[start + 2] & 255) << 8)
+ | ((bytes[start + 1] & 255) << 16)
+ | ((bytes[start] & 255) << 24);
+ return value;
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java (revision 0)
@@ -0,0 +1,161 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.PlainSocketImpl;
+
+/**
+ * This class was added so we can create sockets without options that were
+ * needed for server sockets. It just overrides create so that we call new
+ * natives which only set the options required for plain sockets. In order to
+ * preserve behaviour of older versions the create PlainSocketImpl was left as
+ * is and this new class was added. For newer versions an instance of this class
+ * is used, for earlier versions the original PlainSocketImpl is used.
+ */
+class PlainSocketImpl2 extends PlainSocketImpl {
+
+ public PlainSocketImpl2(FileDescriptor fd, int localport, InetAddress addr, int port) {
+ super();
+ super.fd = fd;
+ super.localport = localport;
+ super.address = addr;
+ super.port = port;
+ }
+
+ public PlainSocketImpl2(){
+ super();
+ }
+
+ /**
+ * Answer the result of attempting to create a stream socket in the IP
+ * stack. This version does not set certain options which were required for
+ * server sockets and which the initial vesrion ended up setting for both
+ * socket and serverSockets as the same method was used to create a socket
+ * for both. We have added a new method so that we can preserve the behavior
+ * of earlier versions
+ *
+ * @param aFD
+ * the socket FileDescriptor
+ * @exception SocketException
+ * if an error occurs while creating the socket
+ */
+ // static native void createStreamSocketImpl2(FileDescriptor aFD,
+ // boolean preferIPv4Stack) throws SocketException;
+ //
+ // /**
+ // * Connect the underlying socket to the nominated remotehost/port.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @param aport
+ // * the remote machine port to connect to
+ // * @param trafficClass
+ // * the traffic class to be used when connecting
+ // * @param inetAddress
+ // * the address to connect to
+ // * @exception SocketException
+ // * if an error occurs while connecting
+ // */
+ // static native void connectStreamSocketImpl2(FileDescriptor aFD, int
+ // aport,
+ // int trafficClass, InetAddress inetAddress) throws IOException;
+ //
+ // /**
+ // * Connect the underlying socket to the nominated remotehost/port.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @param aport
+ // * the remote machine port to connect to
+ // * @param timeout
+ // * timeout after which SocketTimeoutException will be thrown
+ // * @param trafficClass
+ // * the traffic class to be used when connecting
+ // * @param inetAddress
+ // * the address to connect to
+ // * @exception SocketException
+ // * if an error occurs while connecting
+ // * @exception SocketTimeoutException
+ // * if a timeout occurs while trying to connect
+ // */
+ // static native void connectStreamWithTimeoutSocketImpl2(FileDescriptor
+ // aFD,
+ // int aport, int timeout, int trafficClass, InetAddress inetAddress)
+ // throws IOException;
+ /**
+ * Creates a new unconnected socket. If streaming is true, create a stream
+ * socket, else a datagram socket. The deprecated datagram usage is not
+ * supported and will throw an exception.
+ *
+ * @param isStreaming
+ * true, if the socket is type streaming
+ * @exception SocketException
+ * if an error occurs while creating the socket
+ */
+ protected void create(boolean isStreaming) throws IOException {
+ streaming = isStreaming;
+ if (isStreaming) {
+ netImpl.createSocket(fd, NetUtil.preferIPv4Stack());
+ } else {
+ netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
+ }
+ }
+
+ /**
+ * Send the data to the nominated target address
+ * and port. These values are derived from the
+ * DatagramPacket to reduce the field calls within JNI.
+ *
+ * @param fd
+ * the socket FileDescriptor
+ * @param data
+ * the data buffer of the packet
+ * @param length
+ * the length of the data buffer in the packet
+ * @param port
+ * the target host port
+ * @param inetAddress
+ * the address to send the datagram on
+ *
+ * @exception IOException
+ * upon an read error or timeout
+ */
+ // static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
+ // int offset, int length, int port, InetAddress inetAddress)
+ // throws IOException;
+ //
+ // /**
+ // * Bind the socket to the port/localhost in the IP stack.
+ // *
+ // * @param aFD
+ // * the socket descriptor
+ // * @param port
+ // * the option selector
+ // * @param inetAddress
+ // * the address to be used
+ // *
+ // * @throws SocketException
+ // * if bind operation fails
+ // */
+ // static native void socketBindImpl2(FileDescriptor aFD, int port,
+ // InetAddress inetAddress) throws SocketException;
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java (revision 0)
@@ -0,0 +1,169 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.SocketImpl;
+
+import org.apache.harmony.luni.net.PlainSocketImpl;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * The SocketInputStream supports the streamed reading of bytes from a socket.
+ * Multiple streams may be opened on a socket, so care should be taken to manage
+ * opened streams and coordinate read operations between threads.
+ */
+class SocketInputStream extends InputStream {
+
+ private static final String ERRCODE_OFFSETCOUNT_OUTOFBOUND = "K002f"; //$NON-NLS-1$
+
+ private static final String ERRCODE_OFFSET_OUTOFBOUND = "K002e"; //$NON-NLS-1$
+
+ private static final String ERRCODE_BUFFER_NULL = "K0047"; //$NON-NLS-1$
+
+ PlainSocketImpl socket;
+
+ /**
+ * Constructs a SocketInputStream for the socket. Read
+ * operations are forwarded to the socket.
+ *
+ * @param socket
+ * the socket to be read
+ * @see Socket
+ */
+ public SocketInputStream(SocketImpl socket) {
+ super();
+ this.socket = (PlainSocketImpl) socket;
+ }
+
+ /**
+ * Answer the number of bytes that may be read without blocking. Zero
+ * indicates a read operation would block. This call itself does not block,
+ * but may throw an IOException.
+ *
+ * @return int the number of bytes that may be read without blocking
+ * @exception IOException
+ * thrown if an error occurs during the test
+ */
+ public int available() throws IOException {
+ return socket.available();
+ }
+
+ /**
+ * Close the stream and the underlying socket.
+ *
+ * @exception IOException
+ * thrown if an error occurs during the close
+ */
+ public void close() throws IOException {
+ socket.close();
+ super.close();
+ }
+
+ /**
+ * Read a single byte from the socket, answering the value as an
+ * int. This call may block indefinitely, depending upon
+ * whether data is available and whether the read timeout option has been
+ * set on the socket. A value of -1 indicates 'end-of-file'.
+ *
+ * @return int the value read
+ * @exception IOException
+ * thrown if an error occurs during the read
+ */
+ public int read() throws IOException {
+ byte[] buffer = new byte[1];
+ int result = socket.read(buffer, 0, 1);
+ return (-1 == result) ? result : buffer[0] & 0xFF;
+ }
+
+ /**
+ * Read a buffer.length number of bytes from the socket, into the
+ * buffer. This call may block indefinitely, depending upon
+ * whether data is available and whether the read timeout option has been
+ * set on the socket. The number of bytes actually read is returned; a value
+ * of -1 indicates 'end-of-file'.
+ *
+ * @param buffer
+ * the buffer to read into
+ * @return int the number of bytes actually read
+ * @exception IOException
+ * thrown if an error occurs during the read
+ */
+ public int read(byte[] buffer) throws IOException {
+ return read(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Read a count number of bytes from the socket, into the
+ * buffer at an offset. This call may block
+ * indefinitely, depending upon whether data is available and whether the
+ * read timeout option has been set on the socket. The number of bytes
+ * actually read is returned; a value of -1 indicates 'end-of-file'.
+ *
+ * @param buffer
+ * the buffer to read into
+ * @param offset
+ * the offset into the buffer to start filling
+ * @param count
+ * the maximum number of bytes to read
+ * @return int the number of bytes actually read
+ * @exception IOException,
+ * ArrayIndexOutOfBoundsException thrown if the argument
+ * bounds are incorrect or an error occurs during the read
+ */
+ public int read(byte[] buffer, int offset, int count) throws IOException {
+ if (null == buffer) {
+ throw new IOException(Msg.getString(ERRCODE_BUFFER_NULL));
+ }
+
+ if (0 == count) {
+ return 0;
+ }
+
+ if (0 > offset || offset >= buffer.length) {
+ throw new ArrayIndexOutOfBoundsException(Msg
+ .getString(ERRCODE_OFFSET_OUTOFBOUND));
+ }
+ if (0 > count || offset + count > buffer.length) {
+ throw new ArrayIndexOutOfBoundsException(Msg
+ .getString(ERRCODE_OFFSETCOUNT_OUTOFBOUND));
+ }
+
+ return socket.read(buffer, offset, count);
+ }
+
+ /**
+ * Skips n number of bytes in this InputStream. Subsequent
+ * read()'s will not return these bytes unless
+ * reset() is used. This method may perform multiple reads to
+ * read n bytes. This implementation reads n
+ * bytes into a temporary buffer.
+ *
+ * @param n
+ * the number of bytes to skip.
+ * @return the number of bytes actually skipped.
+ *
+ * @exception java.io.IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ public long skip(long n) throws IOException {
+ return (0 == n) ? 0 : super.skip(n);
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/NetUtil.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/NetUtil.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/NetUtil.java (revision 0)
@@ -0,0 +1,63 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.security.AccessController;
+
+import com.ibm.oti.util.PriviAction;
+
+public class NetUtil {
+
+ /*
+ * FIXME: enhance performance to cache the values
+ */
+
+ /**
+ * Answer whether to use a SOCKS proxy.
+ *
+ * @return boolean
+ */
+ public static boolean usingSocks() {
+ String proxySet = (String) AccessController
+ .doPrivileged(new PriviAction("socksProxySet"));
+ if (proxySet != null) {
+ return proxySet.toLowerCase().equals("true");
+ }
+ return AccessController.doPrivileged(new PriviAction("socksProxyHost")) != null;
+ }
+
+ /**
+ * Answer whether to prefer IPV6 address
+ *
+ * @return boolean
+ */
+ public static boolean preferIPv6Addresses() {
+ String result = (String) AccessController.doPrivileged(new PriviAction(
+ "java.net.preferIPv6Addresses"));
+ return "true".equals(result);
+ }
+
+ /**
+ * Answer whether to prefer IPV4 stack
+ *
+ * @return boolean
+ */
+ public static boolean preferIPv4Stack() {
+ String result = (String) AccessController.doPrivileged(new PriviAction(
+ "java.net.preferIPv4Stack"));
+ return "true".equals(result);
+ }
+
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java (revision 0)
@@ -0,0 +1,54 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+
+import org.apache.harmony.luni.platform.Platform;
+
+
+/**
+ * This class was added so we can create sockets with options that are needed
+ * for server sockets. It just overrides create so that we call new natives
+ * which only set the options required for server sockets. In order to preserve
+ * behaviour of older versions the create PlainSocketImpl was left as is and
+ * this new class was added. For newer versions an instance of this class is
+ * used, for earlier versions the original PlainSocketImpl is used.
+ */
+class PlainMulticastSocketImpl extends PlainDatagramSocketImpl {
+
+ // /**
+ // * Answer the result of attempting to create a multicast socket in the IP
+ // * stack. Any special options required for server sockets will be set by
+ // * this method.
+ // *
+ // * @param aFD
+ // * the socket FileDescriptor
+ // * @exception SocketException
+ // * if an error occurs while creating the socket
+ // */
+ // static native void createMulticastSocketImpl(FileDescriptor aFD,
+ // boolean preferIPv4Stack) throws SocketException;
+
+ /**
+ * Allocate the socket descriptor in the IP stack.
+ */
+ public void create() throws SocketException {
+ Platform.getNetworkSystem()
+ .createMulticastSocket(fd, NetUtil.preferIPv4Stack());
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java (revision 0)
@@ -0,0 +1,78 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.PlainSocketImpl;
+
+/**
+ * This class was added so we can create sockets with options that are needed
+ * for server sockets. It just overrides create so that we call new natives
+ * which only set the options required for server sockets. In order to preserve
+ * behaviour of older versions the create PlainSocketImpl was left as is and
+ * this new class was added. For newer versions an instance of this class is
+ * used, for earlier versions the original PlainSocketImpl is used.
+ */
+class PlainServerSocketImpl extends PlainSocketImpl {
+
+ public PlainServerSocketImpl(){
+ super();
+ }
+
+ public PlainServerSocketImpl(FileDescriptor fd){
+ super();
+ this.fd = fd;
+ }
+
+ /**
+ * Answer the result of attempting to create a server stream socket in the
+ * IP stack. Any special options required for server sockets will be set by
+ * this method.
+ *
+ * @param aFD
+ * the socket FileDescriptor
+ * @exception SocketException
+ * if an error occurs while creating the socket
+ */
+ // static native void createServerStreamSocketImpl(FileDescriptor aFD,
+ // boolean preferIPv4Stack) throws SocketException;
+ /**
+ * Creates a new unconnected socket. If streaming is true, create a stream
+ * socket, else a datagram socket. The deprecated datagram usage is not
+ * supported and will throw an exception.
+ *
+ * @param isStreaming
+ * true, if the socket is type streaming
+ * @exception SocketException
+ * if an error occurs while creating the socket
+ */
+ protected void create(boolean isStreaming) throws SocketException {
+ streaming = isStreaming;
+ // if (isStreaming) {
+ // createServerStreamSocketImpl(fd, Socket.preferIPv4Stack());
+ // } else {
+ // createDatagramSocketImpl(fd, Socket.preferIPv4Stack());
+ // }
+ if (isStreaming) {
+ netImpl.createServerStreamSocket(fd, NetUtil.preferIPv4Stack());
+ } else {
+ netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
+ }
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java (revision 0)
@@ -0,0 +1,57 @@
+/* Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.net.DatagramSocketImpl;
+import java.net.InetAddress;
+import java.net.SocketImpl;
+
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
+import org.apache.harmony.luni.net.PlainMulticastSocketImpl;
+import org.apache.harmony.luni.net.PlainServerSocketImpl;
+import org.apache.harmony.luni.net.PlainSocketImpl2;
+
+public class SocketImplProvider {
+
+ public static SocketImpl getSocketImpl(){
+ return new PlainSocketImpl2();
+ }
+
+ public static SocketImpl getSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port){
+ return new PlainSocketImpl2(fd, localport, addr, port);
+ }
+
+ public static SocketImpl getServerSocketImpl(){
+ return new PlainServerSocketImpl();
+ }
+
+ public static SocketImpl getServerSocketImpl(FileDescriptor fd){
+ return new PlainServerSocketImpl(fd);
+ }
+
+ public static DatagramSocketImpl getDatagramSocketImpl(){
+ return new PlainDatagramSocketImpl();
+ }
+
+ public static DatagramSocketImpl getMulticastSocketImpl(){
+ return new PlainMulticastSocketImpl();
+ }
+
+ public static DatagramSocketImpl getDatagramSocketImpl(FileDescriptor fd, int localPort) {
+ return new PlainDatagramSocketImpl(fd, localPort);
+ }
+
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketOutputStream.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketOutputStream.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/SocketOutputStream.java (revision 0)
@@ -0,0 +1,116 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.SocketImpl;
+
+import org.apache.harmony.luni.net.PlainSocketImpl;
+
+class SocketOutputStream extends OutputStream {
+
+ private static final String ERRCODE_BUFFER_NULL = "K0047"; //$NON-NLS-1$
+
+ private static final String ERRCODE_OFFSET_OUTOFBOUND = "K002f"; //$NON-NLS-1$
+
+ PlainSocketImpl socket;
+
+ /**
+ * Constructs a SocketOutputStream for the socket. Write
+ * operations are forwarded to the socket.
+ *
+ * @param socket
+ * the socket to be written
+ * @see Socket
+ */
+
+ public SocketOutputStream(SocketImpl socket) {
+ super();
+ this.socket = (PlainSocketImpl) socket;
+ }
+
+ /**
+ * Close the stream and the underlying socket.
+ *
+ * @exception IOException
+ * thrown if an error occurs during the close
+ */
+
+ public void close() throws IOException {
+ socket.close();
+ super.close();
+ }
+
+ /**
+ * Write the buffer to the socket.
+ *
+ * @param buffer
+ * the buffer to write
+ * @exception IOException
+ * thrown if an error occurs during the write
+ */
+ public void write(byte[] buffer) throws IOException {
+ socket.write(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Write the count number of bytes from the
+ * buffer to the socket, starting at offset.
+ *
+ * @param buffer
+ * the buffer to write
+ * @param offset
+ * the offset in buffer to start writing
+ * @param count
+ * the number of bytes to write
+ * @exception IOException,
+ * IndexOutOfBoundsException thrown if an error occurs during
+ * the write
+ */
+ public void write(byte[] buffer, int offset, int count) throws IOException {
+ // avoid int overflow
+ if (buffer != null) {
+ if (0 <= offset && offset <= buffer.length && 0 <= count
+ && count <= buffer.length - offset) {
+ socket.write(buffer, offset, count);
+ } else {
+ throw new ArrayIndexOutOfBoundsException(com.ibm.oti.util.Msg
+ .getString(ERRCODE_OFFSET_OUTOFBOUND));
+ }
+ } else {
+ throw new NullPointerException(com.ibm.oti.util.Msg
+ .getString(ERRCODE_BUFFER_NULL));
+ }
+ }
+
+ /**
+ * Write a single byte, the lowest-order byte from an int to
+ * the socket.
+ *
+ * @param oneByte
+ * the value to write
+ * @exception IOException
+ * thrown if an error occurs during the write
+ */
+ public void write(int oneByte) throws IOException {
+ byte[] buffer = new byte[1];
+ buffer[0] = (byte) (oneByte & 0xFF);
+
+ socket.write(buffer, 0, 1);
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/GenericIPMreq.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/GenericIPMreq.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/GenericIPMreq.java (revision 0)
@@ -0,0 +1,107 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+
+/**
+ * This class provides is used to pass the information required in an ip_mreq or
+ * ip6_mreq structure to java natives. We don't have accessor methods as it is
+ * more straight forward in the natives to simply access the fields directly
+ */
+final class GenericIPMreq {
+
+ // private members
+ private InetAddress multiaddr;
+
+ private InetAddress interfaceAddr;
+
+ private boolean isIPV6Address;
+
+ private int interfaceIdx;
+
+ /**
+ * This constructor is used to create an instance of the object
+ *
+ * @param addr
+ * multicast address to join/leave
+ *
+ */
+ GenericIPMreq(InetAddress addr) {
+ multiaddr = addr;
+ interfaceAddr = null;
+ interfaceIdx = 0;
+ init();
+ }
+
+ /**
+ * This constructor is used to create an instance of the object
+ *
+ * @param addr
+ * multicast address to join/leave
+ * @param netInterface
+ * the NetworkInterface object identifying the interface on which
+ * to join/leave
+ *
+ */
+ GenericIPMreq(InetAddress addr, NetworkInterface netInterface) {
+ multiaddr = addr;
+ if (null != netInterface) {
+ // TODO check if necessary
+ //interfaceIdx = netInterface.getIndex();
+
+ // here we need to get the first IPV4 address as we only use it if
+ // we
+ // are settting the interface for an IPV4 multicast socket. For
+ // adds/drops on
+ // IPV6 addresses we use the index within the networkInterface
+ interfaceAddr = null;
+ Enumeration theAddresses = netInterface.getInetAddresses();
+ if ((addr instanceof Inet4Address) && (theAddresses != null)) {
+ boolean found = false;
+ while ((theAddresses.hasMoreElements()) && (found != true)) {
+ InetAddress theAddress = (InetAddress) theAddresses
+ .nextElement();
+ if (theAddress instanceof Inet4Address) {
+ interfaceAddr = theAddress;
+ found = true;
+ }
+ }
+ }
+ } else {
+ // network interface is null so we just want to defer the decision
+ // to
+ // the system
+ interfaceIdx = 0;
+ interfaceAddr = null;
+ }
+ init();
+ }
+
+ /**
+ * This method does any required initialization for the constructors
+ */
+ private void init() {
+ // set the flag indicating if the multicast address is an IPV6 address
+ // or not
+ isIPV6Address = ((multiaddr != null) && (multiaddr instanceof Inet6Address));
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/Socks4Message.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/Socks4Message.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/Socks4Message.java (revision 0)
@@ -0,0 +1,251 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.UnsupportedEncodingException;
+
+class Socks4Message {
+ protected byte[] buffer;
+
+ final static private int SOCKS_VERSION = 4;
+
+ final static public int COMMAND_CONNECT = 1;
+
+ final static public int COMMAND_BIND = 2;
+
+ final static public int RETURN_SUCCESS = 90;
+
+ final static public int RETURN_FAILURE = 91;
+
+ final static public int RETURN_CANNOT_CONNECT_TO_IDENTD = 92;
+
+ final static public int RETURN_DIFFERENT_USER_IDS = 93;
+
+ final static protected int INDEX_VERSION = 0;
+
+ final static private int INDEX_COMMAND = 1;
+
+ final static private int INDEX_PORT = 2;
+
+ final static private int INDEX_IP = 4;
+
+ final static private int INDEX_USER_ID = 8;
+
+ final static private int BUFFER_LENGTH = 256;
+
+ final static public int REPLY_LENGTH = 8;
+
+ final static private int MAX_USER_ID_LENGTH = BUFFER_LENGTH - INDEX_USER_ID;
+
+ public Socks4Message() {
+ super();
+ buffer = new byte[BUFFER_LENGTH];
+ setVersionNumber(SOCKS_VERSION);
+ }
+
+ /**
+ * Get the request's command or result.
+ */
+ public int getCommandOrResult() {
+ return buffer[INDEX_COMMAND];
+ }
+
+ /**
+ * Set the request's command or result.
+ */
+ public void setCommandOrResult(int command) {
+ buffer[INDEX_COMMAND] = (byte) command;
+ }
+
+ /**
+ * Answer the request's port number.
+ */
+ public int getPort() {
+ return getInt16(INDEX_PORT);
+ }
+
+ /**
+ * Set the request's port number.
+ */
+ public void setPort(int port) {
+ setInt16(INDEX_PORT, port);
+ }
+
+ /*
+ * Answer the IP address of the request as an integer.
+ */
+ public int getIP() {
+ return getInt32(INDEX_IP);
+ }
+
+ /**
+ * Set the IP address. This expects an array of four bytes in host order.
+ */
+ public void setIP(byte[] ip) {
+ buffer[INDEX_IP] = ip[0];
+ buffer[INDEX_IP + 1] = ip[1];
+ buffer[INDEX_IP + 2] = ip[2];
+ buffer[INDEX_IP + 3] = ip[3];
+ }
+
+ /**
+ * Answer the user id for authentication.
+ */
+ public String getUserId() {
+ return getString(INDEX_USER_ID, MAX_USER_ID_LENGTH);
+ }
+
+ /**
+ * Set the user id for authentication.
+ */
+ public void setUserId(String id) {
+ setString(INDEX_USER_ID, MAX_USER_ID_LENGTH, id);
+ }
+
+ /**
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("");
+ buf.append("Version: ");
+ buf.append(Integer.toHexString(getVersionNumber()));
+ buf.append(" Command: ");
+ buf.append(Integer.toHexString(getCommandOrResult()));
+ buf.append(" Port: ");
+ buf.append(getPort());
+ buf.append(" IP: ");
+ buf.append(Integer.toHexString(getIP()));
+ buf.append(" User ID: ");
+ buf.append(getUserId());
+ return buf.toString();
+ }
+
+ /**
+ * Answer the total number of bytes used for the request. This method
+ * searches for the end of the user id, then searches for the end of the
+ * password and returns the final index as the requests length.
+ */
+ public int getLength() {
+ int index = 0;
+
+ // Look for the end of the user id.
+ for (index = INDEX_USER_ID; buffer[index] != 0; index++) {
+ /*
+ * Finds the end of the user id by searching for the null
+ * termination of the user id string.
+ */
+ }
+
+ // Increment the index to include the NULL character in the length;
+ index++;
+ return index;
+ }
+
+ /**
+ * Answer an error string corresponding to the given error value.
+ */
+ public String getErrorString(int error) {
+ switch (error) {
+ case RETURN_FAILURE:
+ return com.ibm.oti.util.Msg.getString("K00cd");
+ case RETURN_CANNOT_CONNECT_TO_IDENTD:
+ return com.ibm.oti.util.Msg.getString("K00ce");
+ case RETURN_DIFFERENT_USER_IDS:
+ return com.ibm.oti.util.Msg.getString("K00cf");
+ default:
+ return com.ibm.oti.util.Msg.getString("K00d0");
+ }
+ }
+
+ /**
+ * Answer the message's byte buffer.
+ */
+ public byte[] getBytes() {
+ return buffer;
+ }
+
+ /**
+ * Get a 16 bit integer from the buffer at the offset given.
+ */
+ private int getInt16(int offset) {
+ return (((buffer[offset] & 0xFF) << 8) + (buffer[offset + 1] & 0xFF));
+ }
+
+ /**
+ * Get a 32 bit integer from the buffer at the offset given.
+ */
+ private int getInt32(int offset) {
+ return ((buffer[offset + 3] & 0xFF)
+ + ((buffer[offset + 2] & 0xFF) << 8)
+ + ((buffer[offset + 1] & 0xFF) << 16) + ((buffer[offset + 0] & 0xFF) << 24));
+ }
+
+ /**
+ * Get a String from the buffer at the offset given. The method reads until
+ * it encounters a null value or reaches the maxLength given.
+ */
+ private String getString(int offset, int maxLength) {
+ int index = offset;
+ int lastIndex = index + maxLength;
+ String result;
+
+ while (index < lastIndex && (buffer[index] != 0)) {
+ index++;
+ }
+ try {
+ result = new String(buffer, offset, index - offset, "ISO8859_1");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.toString());
+ }
+ return result;
+ }
+
+ /**
+ * Answer the SOCKS version number. Should always be 4.
+ */
+ private int getVersionNumber() {
+ return buffer[INDEX_VERSION];
+ }
+
+ /**
+ * Put a 16 bit integer into the buffer at the offset given.
+ */
+ private void setInt16(int offset, int value) {
+ buffer[offset] = (byte) (value >>> 8 & 0xFF);
+ buffer[offset + 1] = (byte) (value & 0xFF);
+ }
+
+ /**
+ * Put a string into the buffer at the offset given.
+ */
+ private void setString(int offset, int maxLength, String theString) {
+ byte[] stringBytes;
+ try {
+ stringBytes = theString.getBytes("ISO8859_1");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.toString());
+ }
+ int length = Math.min(stringBytes.length, maxLength);
+ System.arraycopy(stringBytes, 0, buffer, offset, length);
+ buffer[offset + length] = 0;
+ }
+
+ /**
+ * Set the SOCKS version number. This should always be 4.
+ */
+ private void setVersionNumber(int number) {
+ buffer[INDEX_VERSION] = (byte) number;
+ }
+}
Index: E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
===================================================================
--- E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java (revision 0)
+++ E:/projects/clear/eclipse/workspace/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java (revision 0)
@@ -0,0 +1,663 @@
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * 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 org.apache.harmony.luni.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOptions;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.security.AccessController;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.PlainSocketImpl;
+import org.apache.harmony.luni.net.SocketInputStream;
+import org.apache.harmony.luni.net.SocketOutputStream;
+import org.apache.harmony.luni.net.Socks4Message;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+
+import com.ibm.oti.util.Msg;
+import com.ibm.oti.util.PriviAction;
+
+/**
+ * A concrete connected-socket implementation.
+ */
+class PlainSocketImpl extends SocketImpl {
+
+ // Const copy from socket
+
+ static final int MULTICAST_IF = 1;
+
+ static final int MULTICAST_TTL = 2;
+
+ static final int TCP_NODELAY = 4;
+
+ static final int FLAG_SHUTDOWN = 8;
+
+ // For SOCKS support. A SOCKS bind() uses the last
+ // host connected to in its request.
+ static private InetAddress lastConnectedAddress;
+
+ static private int lastConnectedPort;
+
+ private boolean tcpNoDelay = true;
+
+ private Object connectLock = new Object();
+
+ // used to store the trafficClass value which is simply returned
+ // as the value that was set. We also need it to pass it to methods
+ // that specify an address packets are going to be sent to
+ private int trafficClass = 0;
+
+ protected INetworkSystem netImpl = Platform.getNetworkSystem();
+
+ public int receiveTimeout = 0;
+
+ public boolean streaming = true;
+
+ public boolean shutdownInput = false;
+
+ /**
+ * Accepts a connection on the provided socket, by calling the IP stack.
+ *
+ * @param newImpl
+ * the socket to accept connections on
+ * @exception SocketException
+ * if an error occurs while accepting
+ */
+ protected void accept(SocketImpl newImpl) throws IOException {
+ if (NetUtil.usingSocks()) {
+ ((PlainSocketImpl) newImpl).socksBind();
+ ((PlainSocketImpl) newImpl).socksAccept();
+ return;
+ }
+
+ try {
+ netImpl.acceptStreamSocket(fd, newImpl, ((PlainSocketImpl) newImpl)
+ .getFD(), receiveTimeout);
+ } catch (InterruptedIOException e) {
+ throw new SocketTimeoutException(e.getMessage());
+ }
+ ((PlainSocketImpl) newImpl).setLocalport(getLocalPort());
+ }
+
+ /**
+ * Answer the number of bytes that may be read from this socket without
+ * blocking. This call does not block.
+ *
+ * @return int the number of bytes that may be read without blocking
+ * @exception SocketException
+ * if an error occurs while peeking
+ */
+
+ protected synchronized int available() throws IOException {
+ // we need to check if the input has been shutdown. If so
+ // we should return that there is no data to be read
+ if (shutdownInput == true) {
+ return 0;
+ }
+ return netImpl.availableStream(fd);
+ }
+
+ /**
+ * Binds this socket to the specified local host/port. Binding to the 0 port
+ * implies binding to any available port. By not making the assignment to
+ * the instVar, the getLocalPort method will lazily go to the stack and
+ * query for the assigned port
+ *
+ * @param anAddr
+ * the local machine address to bind the socket to
+ * @param aPort
+ * the port on the local machine to bind the socket to
+ * @exception IOException
+ * if an error occurs while binding
+ */
+ protected void bind(InetAddress anAddr, int aPort) throws IOException {
+ if (NetUtil.usingSocks()) {
+ socksBind();
+ return;
+ }
+ netImpl.bind(fd, aPort, anAddr);
+ // PlainSocketImpl2.socketBindImpl2(fd, aPort, anAddr);
+ address = anAddr;
+ if (0 != aPort) {
+ localport = aPort;
+ } else {
+ localport = netImpl.getSocketLocalPort(fd,
+ NetUtil.preferIPv6Addresses());
+ }
+ }
+
+ /**
+ * Close the socket. Usage thereafter is invalid.
+ *
+ * @exception IOException
+ * if an error occurs while closing
+ */
+ protected void close() throws IOException {
+ synchronized (fd) {
+ if (fd.valid()) {
+ if ((netImpl.getSocketFlags() & FLAG_SHUTDOWN) != 0) {
+ try {
+ shutdownOutput();
+ } catch (Exception e) {
+ }
+ }
+ netImpl.socketClose(fd);
+ fd = new FileDescriptor();
+ }
+ }
+ }
+
+ /**
+ * Connects this socket to the specified remote host/port. This method
+ * assumes the sender has verified the host with the security policy.
+ *
+ * @param aHost
+ * the remote host to connect to
+ * @param aPort
+ * the remote port to connect to
+ * @exception IOException
+ * if an error occurs while connecting
+ */
+ protected void connect(String aHost, int aPort) throws IOException {
+ // InetAddress anAddr = InetAddress.getHostByNameImpl(aHost,
+ // preferIPv6Addresses());
+ InetAddress anAddr = netImpl.getHostByName(aHost,
+ NetUtil.preferIPv6Addresses());
+ connect(anAddr, aPort);
+ }
+
+ /**
+ * Connects this socket to the specified remote host address/port.
+ *
+ * @param anAddr
+ * the remote host address to connect to
+ * @param aPort
+ * the remote port to connect to
+ * @exception IOException
+ * if an error occurs while connecting
+ */
+ protected void connect(InetAddress anAddr, int aPort) throws IOException {
+ connect(anAddr, aPort, 0);
+ }
+
+ /**
+ * Connects this socket to the specified remote host address/port.
+ *
+ * @param anAddr
+ * the remote host address to connect to
+ * @param aPort
+ * the remote port to connect to
+ * @param timeout
+ * a timeout where supported. 0 means no timeout
+ * @exception IOException
+ * if an error occurs while connecting
+ */
+ private void connect(InetAddress anAddr, int aPort, int timeout)
+ throws IOException {
+ InetAddress address = anAddr.isAnyLocalAddress() ? InetAddress
+ .getByName("localhost") : anAddr;
+
+ try {
+ if (streaming) {
+ if (NetUtil.usingSocks()) {
+ socksConnect(anAddr, aPort, 0);
+ } else {
+ if (timeout == 0) {
+ // PlainSocketImpl2.connectStreamSocketImpl2(fd, aPort,
+ // trafficClass, address);
+ netImpl.connect(fd, trafficClass, anAddr, aPort);
+ } else {
+ // PlainSocketImpl2.connectStreamWithTimeoutSocketImpl2(
+ // fd, aPort, timeout, trafficClass, address);
+ netImpl.connectStreamWithTimeoutSocket(fd, aPort,
+ timeout, trafficClass, anAddr);
+ }
+ }
+ }
+ } catch (ConnectException e) {
+ throw new ConnectException(anAddr + ":" + aPort + " - "
+ + e.getMessage());
+ }
+ super.address = anAddr;
+ super.port = aPort;
+ }
+
+ /**
+ * Creates a new unconnected socket. If streaming is true, create a stream
+ * socket, else a datagram socket. The deprecated datagram usage is not
+ * supported and will throw an exception.
+ *
+ * @param streaming
+ * true, if the socket is type streaming
+ * @exception SocketException
+ * if an error occurs while creating the socket
+ */
+ protected void create(boolean streaming) throws IOException {
+ this.streaming = streaming;
+ // if (streaming) {
+ // createStreamSocketImpl(fd, Socket.preferIPv4Stack());
+ // } else {
+ // createDatagramSocketImpl(fd, Socket.preferIPv4Stack());
+ // }
+
+ if (streaming) {
+ netImpl.createStreamSocket(fd, NetUtil.preferIPv4Stack());
+ } else {
+ netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
+ }
+ }
+
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ /**
+ * Answer the socket input stream.
+ *
+ * @return InputStream an InputStream on the socket
+ * @exception IOException
+ * thrown if an error occurs while accessing the stream
+ */
+ protected synchronized InputStream getInputStream() throws IOException {
+ if (!fd.valid()) {
+ throw new SocketException(Msg.getString("K003d"));
+ }
+
+ return new SocketInputStream(this);
+ }
+
+ /**
+ * Answer the nominated socket option. Receive timeouts are maintained in
+ * Java, rather than in the JNI code.
+ *
+ * @param optID
+ * the socket option to retrieve
+ * @return Object the option value
+ * @exception SocketException
+ * thrown if an error occurs while accessing the option
+ */
+ public Object getOption(int optID) throws SocketException {
+ if (optID == SocketOptions.SO_TIMEOUT) {
+ return new Integer(receiveTimeout);
+ } else if (optID == SocketOptions.IP_TOS) {
+ return new Integer(trafficClass);
+ } else {
+ // Call the native first so there will be
+ // an exception if the socket if closed.
+ Object result = netImpl.getSocketOption(fd, optID);
+ if (optID == SocketOptions.TCP_NODELAY
+ && (netImpl.getSocketFlags() & TCP_NODELAY) != 0) {
+ return new Boolean(tcpNoDelay);
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Answer the socket output stream.
+ *
+ * @return OutputStream an OutputStream on the socket
+ * @exception IOException
+ * thrown if an error occurs while accessing the stream
+ */
+ protected synchronized OutputStream getOutputStream() throws IOException {
+ if (!fd.valid()) {
+ throw new SocketException(Msg.getString("K003d"));
+ }
+ return new SocketOutputStream(this);
+ }
+
+ /**
+ * Listen for connection requests on this stream socket. Incoming connection
+ * requests are queued, up to the limit nominated by backlog. Additional
+ * requests are rejected. listen() may only be invoked on stream sockets.
+ *
+ * @param backlog
+ * the max number of outstanding connection requests
+ * @exception IOException
+ * thrown if an error occurs while listening
+ */
+ protected void listen(int backlog) throws IOException {
+ if (NetUtil.usingSocks()) {
+ // Do nothing for a SOCKS connection. The listen occurs on the
+ // server during the bind.
+ return;
+ }
+ // listenStreamSocketImpl(fd, backlog);
+ netImpl.listenStreamSocket(fd, backlog);
+ }
+
+ /**
+ * Set the nominated socket option. Receive timeouts are maintained in Java,
+ * rather than in the JNI code.
+ *
+ * @param optID
+ * the socket option to set
+ * @param val
+ * the option value
+ * @exception SocketException
+ * thrown if an error occurs while setting the option
+ */
+ public void setOption(int optID, Object val) throws SocketException {
+ if (optID == SocketOptions.SO_TIMEOUT) {
+ receiveTimeout = ((Integer) val).intValue();
+ } else {
+ try {
+ netImpl.setSocketOption(fd, optID, val);
+ if (optID == SocketOptions.TCP_NODELAY
+ && (netImpl.getSocketFlags() & TCP_NODELAY) != 0) {
+ tcpNoDelay = ((Boolean) val).booleanValue();
+ }
+ } catch (SocketException e) {
+
+ // we don't through an exception for IP_TOS even if the platform
+ // won't let us set the requested value
+ if (optID != SocketOptions.IP_TOS) {
+ throw e;
+ }
+ }
+
+ // save this value as it is acutally used differently for IPv4 and
+ // IPv6 so we cannot get the value using the getOption. The option
+ // is actually only set for IPv4 and a masked version of the value
+ // will be set as only a subset of the values are allowed on the
+ // socket. Therefore we need to retain it to return the value that
+ // was set. We also need the value to be passed into a number of
+ // natives so that it can be used properly with IPv6
+ if (optID == SocketOptions.IP_TOS) {
+ trafficClass = ((Integer) val).intValue();
+ }
+ }
+ }
+
+ /**
+ * Get the SOCKS proxy server port.
+ */
+ private int socksGetServerPort() {
+ int portValue = -1;
+
+ String proxyPort = (String) AccessController
+ .doPrivileged(new PriviAction("socksProxyPort"));
+
+ if (proxyPort != null) {
+ portValue = Integer.parseInt(proxyPort);
+ }
+ if (portValue < 0) {
+ portValue = 1080;
+ }
+
+ return portValue;
+ }
+
+ /**
+ * Get the InetAddress of the SOCKS proxy server.
+ */
+ private InetAddress socksGetServerAddress() throws UnknownHostException {
+ String proxyName = (String) AccessController
+ .doPrivileged(new PriviAction("socksProxyHost"));
+
+ InetAddress anAddr = netImpl.getHostByName(proxyName,
+ NetUtil.preferIPv6Addresses());
+ return anAddr;
+ }
+
+ /**
+ * Connect using a SOCKS server.
+ */
+ private void socksConnect(InetAddress applicationServerAddress,
+ int applicationServerPort, int timeout) throws IOException {
+ try {
+ if (timeout == 0) {
+ // PlainSocketImpl2.connectStreamSocketImpl2(fd,
+ // socksGetServerPort(), trafficClass,
+ // socksGetServerAddress());
+ netImpl.connect(fd, trafficClass, socksGetServerAddress(),
+ socksGetServerPort());
+ } else {
+ // PlainSocketImpl2.connectStreamWithTimeoutSocketImpl2(fd,
+ // socksGetServerPort(), timeout, trafficClass,
+ // socksGetServerAddress());
+ netImpl.connectStreamWithTimeoutSocket(fd,
+ socksGetServerPort(), timeout, trafficClass,
+ socksGetServerAddress());
+ }
+
+ } catch (Exception e) {
+ throw new SocketException(Msg.getString("K003e", e));
+ }
+
+ socksRequestConnection(applicationServerAddress, applicationServerPort);
+
+ lastConnectedAddress = applicationServerAddress;
+ lastConnectedPort = applicationServerPort;
+ }
+
+ /**
+ * Request a SOCKS connection to the application server given. If the
+ * request fails to complete successfully, an exception is thrown.
+ */
+ private void socksRequestConnection(InetAddress applicationServerAddress,
+ int applicationServerPort) throws IOException {
+ socksSendRequest(Socks4Message.COMMAND_CONNECT,
+ applicationServerAddress, applicationServerPort);
+ Socks4Message reply = socksReadReply();
+ if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) {
+ throw new IOException(reply.getErrorString(reply
+ .getCommandOrResult()));
+ }
+ }
+
+ /**
+ * Perform an accept for a SOCKS bind.
+ */
+ public void socksAccept() throws IOException {
+ Socks4Message reply = socksReadReply();
+ if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) {
+ throw new IOException(reply.getErrorString(reply
+ .getCommandOrResult()));
+ }
+ }
+
+ /**
+ * Shutdown the input portion of the socket.
+ */
+ protected void shutdownInput() throws IOException {
+ shutdownInput = true;
+ // shutdownInputImpl(fd);
+ netImpl.shutdownInput(fd);
+ }
+
+ /**
+ * Shutdown the output portion of the socket.
+ */
+ protected void shutdownOutput() throws IOException {
+ // shutdownOutputImpl(fd);
+ netImpl.shutdownOutput(fd);
+ }
+
+ /**
+ * Bind using a SOCKS server.
+ */
+ private void socksBind() throws IOException {
+ try {
+ // PlainSocketImpl2.connectStreamSocketImpl2(fd,
+ // socksGetServerPort(),
+ // trafficClass, socksGetServerAddress());
+ netImpl.connect(fd, trafficClass, socksGetServerAddress(),
+ socksGetServerPort());
+ } catch (Exception e) {
+ throw new IOException(Msg.getString("K003f", e));
+ }
+
+ // There must be a connection to an application host for the bind to
+ // work.
+ if (lastConnectedAddress == null) {
+ throw new SocketException(Msg.getString("K0040"));
+ }
+
+ // Use the last connected address and port in the bind request.
+ socksSendRequest(Socks4Message.COMMAND_BIND, lastConnectedAddress,
+ lastConnectedPort);
+ Socks4Message reply = socksReadReply();
+
+ if (reply.getCommandOrResult() != Socks4Message.RETURN_SUCCESS) {
+ throw new IOException(reply.getErrorString(reply
+ .getCommandOrResult()));
+ }
+
+ // A peculiarity of socks 4 - if the address returned is 0, use the
+ // original socks server address.
+ if (reply.getIP() == 0) {
+ address = socksGetServerAddress();
+ } else {
+ // IPv6 support not yet required as
+ // currently the Socks4Message.getIP() only returns int,
+ // so only works with IPv4 4byte addresses
+ byte[] replyBytes = new byte[4];
+ intToBytes(reply.getIP(), replyBytes, 0);
+ address = InetAddress.getByAddress(replyBytes);
+ }
+ localport = reply.getPort();
+ }
+
+ /**
+ * Send a SOCKS V4 request.
+ */
+ private void socksSendRequest(int command, InetAddress address, int port)
+ throws IOException {
+ Socks4Message request = new Socks4Message();
+ request.setCommandOrResult(command);
+ request.setPort(port);
+ request.setIP(address.getAddress());
+ request.setUserId("default");
+
+ getOutputStream().write(request.getBytes(), 0, request.getLength());
+ }
+
+ /**
+ * Read a SOCKS V4 reply.
+ */
+ private Socks4Message socksReadReply() throws IOException {
+ Socks4Message reply = new Socks4Message();
+ int bytesRead = 0;
+ while (bytesRead < Socks4Message.REPLY_LENGTH) {
+ bytesRead += getInputStream().read(reply.getBytes(), bytesRead,
+ Socks4Message.REPLY_LENGTH - bytesRead);
+ }
+ return reply;
+ }
+
+ /**
+ * Connect the socket to the host/port specified by the SocketAddress with a
+ * specified timeout.
+ *
+ *
+ * @param remoteAddr
+ * the remote machine address and port to connect to
+ * @param timeout
+ * the millisecond timeout value, the connect will block
+ * indefinitely for a zero value.
+ *
+ * @exception IOException
+ * if a problem occurs during the connect
+ */
+ protected void connect(SocketAddress remoteAddr, int timeout)
+ throws IOException {
+ InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
+ connect(inetAddr.getAddress(), inetAddr.getPort(), timeout);
+ }
+
+ /**
+ * Answer if the socket supports urgent data.
+ */
+ protected boolean supportsUrgentData() {
+ // return !streaming || SocketImpl.supportsUrgentDataImpl(fd);
+ return !streaming || netImpl.supportsUrgentData(fd);
+ }
+
+ /**
+ * Send the single byte of urgent data on the socket.
+ *
+ * @param value
+ * the byte of urgent data
+ *
+ * @exception IOException
+ * when an error occurs sending urgent data
+ */
+ protected void sendUrgentData(int value) throws IOException {
+ // SocketImpl.sendUrgentDataImpl(fd, (byte) value);
+ netImpl.sendUrgentData(fd, (byte) value);
+ }
+
+ FileDescriptor getFD() {
+ return fd;
+ }
+
+ private void setLocalport(int localport) {
+ this.localport = localport;
+ }
+
+ int read(byte[] buffer, int offset, int count) throws IOException {
+ if (shutdownInput) {
+ return -1;
+ }
+ try {
+ // int read = receiveStreamImpl(fd, buffer, offset, count,
+ // receiveTimeout);
+ int read = netImpl.receiveStream(fd, buffer, offset, count,
+ receiveTimeout);
+ if (read == -1) {
+ shutdownInput = true;
+ }
+ return read;
+ } catch (InterruptedIOException e) {
+ throw new SocketTimeoutException(e.getMessage());
+ }
+ }
+
+ int write(byte[] buffer, int offset, int count) throws IOException {
+ if (!streaming) {
+ // PlainSocketImpl2.sendDatagramImpl2(fd, buffer, offset, count,
+ // port,
+ // address);
+ netImpl
+ .sendDatagram2(fd, buffer, offset, count, port, address);
+ }
+ // return sendStreamImpl(fd, buffer, offset, count);
+ return netImpl.sendStream(fd, buffer, offset, count);
+ }
+
+ static void intToBytes(int value, byte bytes[], int start) {
+ // Shift the int so the current byte is right-most
+ // Use a byte mask of 255 to single out the last byte.
+ bytes[start] = (byte) ((value >> 24) & 255);
+ bytes[start + 1] = (byte) ((value >> 16) & 255);
+ bytes[start + 2] = (byte) ((value >> 8) & 255);
+ bytes[start + 3] = (byte) (value & 255);
+ }
+}