SocketType.java
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.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.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.socket;
import jnr.constants.platform.Sock;
import jnr.constants.platform.SocketOption;
import jnr.unixsocket.UnixServerSocketChannel;
import jnr.unixsocket.UnixSocketChannel;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.Channel;
import java.nio.channels.DatagramChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
/**
* Encapsulates behavior across the primary socket types Socket,
* ServerSocket, and Datagramsocket.
*/
public enum SocketType {
SOCKET(Sock.SOCK_STREAM) {
private Socket toSocket(Channel channel) {
return ((SocketChannel)channel).socket();
}
public int getSoTimeout(Channel channel) throws IOException {
return toSocket(channel).getSoTimeout();
}
public void setSoTimeout(Channel channel, int timeout) throws IOException {
toSocket(channel).setSoTimeout(timeout);
}
public boolean getReuseAddress(Channel channel) throws IOException {
return toSocket(channel).getReuseAddress();
}
public void setReuseAddress(Channel channel, boolean reuse) throws IOException {
toSocket(channel).setReuseAddress(reuse);
}
public int getSendBufferSize(Channel channel) throws IOException {
return toSocket(channel).getSendBufferSize();
}
public void setSendBufferSize(Channel channel, int size) throws IOException {
toSocket(channel).setSendBufferSize(size);
}
public int getReceiveBufferSize(Channel channel) throws IOException {
return toSocket(channel).getReceiveBufferSize();
}
public void setReceiveBufferSize(Channel channel, int i) throws IOException {
toSocket(channel).setReceiveBufferSize(i);
}
public boolean getOOBInline(Channel channel) throws IOException {
return toSocket(channel).getOOBInline();
}
public void setOOBInline(Channel channel, boolean b) throws IOException {
toSocket(channel).setOOBInline(b);
}
public int getSoLinger(Channel channel) throws IOException {
return toSocket(channel).getSoLinger();
}
public void setSoLinger(Channel channel, boolean b, int i) throws IOException {
toSocket(channel).setSoLinger(b, i);
}
public boolean getKeepAlive(Channel channel) throws IOException {
return toSocket(channel).getKeepAlive();
}
public void setKeepAlive(Channel channel, boolean b) throws IOException {
toSocket(channel).setKeepAlive(b);
}
public boolean getTcpNoDelay(Channel channel) throws IOException {
return toSocket(channel).getTcpNoDelay();
}
public void setTcpNoDelay(Channel channel, boolean b) throws IOException {
toSocket(channel).setTcpNoDelay(b);
}
public SocketAddress getRemoteSocketAddress(Channel channel) {
return toSocket(channel).getRemoteSocketAddress();
}
public SocketAddress getLocalSocketAddress(Channel channel) {
return toSocket(channel).getLocalSocketAddress();
}
public void shutdownInput(Channel channel)throws IOException {
toSocket(channel).shutdownInput();
}
public void shutdownOutput(Channel channel)throws IOException {
toSocket(channel).shutdownOutput();
}
},
SERVER(Sock.SOCK_STREAM) {
private ServerSocket toSocket(Channel channel) {
return ((ServerSocketChannel)channel).socket();
}
public int getSoTimeout(Channel channel) throws IOException {
return toSocket(channel).getSoTimeout();
}
public void setSoTimeout(Channel channel, int timeout) throws IOException {
toSocket(channel).setSoTimeout(timeout);
}
public boolean getReuseAddress(Channel channel) throws IOException {
return toSocket(channel).getReuseAddress();
}
public void setReuseAddress(Channel channel, boolean reuse) throws IOException {
toSocket(channel).setReuseAddress(reuse);
}
public int getSendBufferSize(Channel channel) throws IOException {
return 0;
}
public void setSendBufferSize(Channel channel, int size) throws IOException {
}
public int getReceiveBufferSize(Channel channel) throws IOException {
return toSocket(channel).getReceiveBufferSize();
}
public void setReceiveBufferSize(Channel channel, int i) throws IOException {
toSocket(channel).setReceiveBufferSize(i);
}
public SocketAddress getLocalSocketAddress(Channel channel) {
return toSocket(channel).getLocalSocketAddress();
}
},
DATAGRAM(Sock.SOCK_DGRAM) {
private DatagramSocket toSocket(Channel channel) {
return ((DatagramChannel)channel).socket();
}
public int getSoTimeout(Channel channel) throws IOException {
return toSocket(channel).getSoTimeout();
}
public void setSoTimeout(Channel channel, int timeout) throws IOException {
toSocket(channel).setSoTimeout(timeout);
}
public boolean getReuseAddress(Channel channel) throws IOException {
return toSocket(channel).getReuseAddress();
}
public void setReuseAddress(Channel channel, boolean reuse) throws IOException {
toSocket(channel).setReuseAddress(reuse);
}
public int getSendBufferSize(Channel channel) throws IOException {
return toSocket(channel).getSendBufferSize();
}
public void setSendBufferSize(Channel channel, int size) throws IOException {
toSocket(channel).setSendBufferSize(size);
}
public int getReceiveBufferSize(Channel channel) throws IOException {
return toSocket(channel).getReceiveBufferSize();
}
public void setReceiveBufferSize(Channel channel, int i) throws IOException {
toSocket(channel).setReceiveBufferSize(i);
}
public boolean getBroadcast(Channel channel) throws IOException {
return toSocket(channel).getBroadcast();
}
public void setBroadcast(Channel channel, boolean b) throws IOException {
toSocket(channel).setBroadcast(b);
}
public SocketAddress getRemoteSocketAddress(Channel channel) {
return toSocket(channel).getRemoteSocketAddress();
}
public SocketAddress getLocalSocketAddress(Channel channel) {
return toSocket(channel).getLocalSocketAddress();
}
},
UNIX(Sock.SOCK_STREAM) {
private UnixSocketChannel toSocket(Channel channel) {
return (UnixSocketChannel)channel;
}
public void shutdownInput(Channel channel)throws IOException {
toSocket(channel).shutdownInput();
}
public void shutdownOutput(Channel channel) throws IOException {
toSocket(channel).shutdownOutput();
}
},
UNKNOWN(Sock.SOCK_STREAM);
public static SocketType forChannel(Channel channel) {
if (channel instanceof SocketChannel) {
return SOCKET;
} else if (channel instanceof ServerSocketChannel) {
return SERVER;
} else if (channel instanceof DatagramChannel) {
return DATAGRAM;
} else if (channel instanceof UnixSocketChannel) {
return UNIX;
}
return UNKNOWN;
}
public int getSoTimeout(Channel channel) throws IOException { return 0; }
public void setSoTimeout(Channel channel, int timeout) throws IOException {}
public boolean getReuseAddress(Channel channel) throws IOException { return false; }
public void setReuseAddress(Channel channel, boolean reuse) throws IOException {}
public int getSendBufferSize(Channel channel) throws IOException { return 0; }
public void setSendBufferSize(Channel channel, int size) throws IOException {}
public int getReceiveBufferSize(Channel channel) throws IOException { return 0; }
public void setReceiveBufferSize(Channel channel, int i) throws IOException {}
public boolean getOOBInline(Channel channel) throws IOException { return false; }
public void setOOBInline(Channel channel, boolean b) throws IOException {}
public int getSoLinger(Channel channel) throws IOException { return 0; }
public void setSoLinger(Channel channel, boolean b, int i) throws IOException {}
public boolean getKeepAlive(Channel channel) throws IOException { return false; }
public void setKeepAlive(Channel channel, boolean b) throws IOException {}
public boolean getTcpNoDelay(Channel channel) throws IOException { return false; }
public void setTcpNoDelay(Channel channel, boolean b) throws IOException {}
public boolean getBroadcast(Channel channel) throws IOException { return false; }
public void setBroadcast(Channel channel, boolean b) throws IOException {}
public void shutdownInput(Channel channel) throws IOException {}
public void shutdownOutput(Channel channel) throws IOException {}
public SocketAddress getRemoteSocketAddress(Channel channel) {
return null;
}
public SocketAddress getLocalSocketAddress(Channel channel) {
return null;
}
public Sock getSocketType() {
return sock;
}
public int getSocketOption(Channel channel, SocketOption option) throws IOException {
switch (option) {
case SO_BROADCAST:
return getBroadcast(channel) ? 1 : 0;
case SO_KEEPALIVE:
return getKeepAlive(channel) ? 1 : 0;
case SO_LINGER: {
int linger = getSoLinger(channel);
return linger < 0 ? 0 : linger;
}
case SO_OOBINLINE:
return getOOBInline(channel) ? 1 : 0;
case SO_RCVBUF:
return getReceiveBufferSize(channel);
case SO_REUSEADDR:
return getReuseAddress(channel) ? 1 : 0;
case SO_SNDBUF:
return getSendBufferSize(channel);
case SO_RCVTIMEO:
case SO_SNDTIMEO:
return getSoTimeout(channel);
case SO_TYPE:
return getSocketType().intValue();
// Can't support the rest with Java
case SO_RCVLOWAT:
return 1;
case SO_SNDLOWAT:
return 2048;
case SO_DEBUG:
case SO_ERROR:
case SO_DONTROUTE:
case SO_TIMESTAMP:
return 0;
}
return 0;
}
public void setSocketOption(Channel channel, SocketOption option, int value) throws IOException {
switch (option) {
case SO_BROADCAST:
setBroadcast(channel, asBoolean(value));
break;
case SO_KEEPALIVE:
setKeepAlive(channel, asBoolean(value));
break;
case SO_LINGER:
setSoLinger(channel, value <= 0, value);
break;
case SO_OOBINLINE:
setOOBInline(channel, asBoolean(value));
break;
case SO_RCVBUF:
setReceiveBufferSize(channel, value);
break;
case SO_REUSEADDR:
setReuseAddress(channel, asBoolean(value));
break;
case SO_SNDBUF:
setSendBufferSize(channel, value);
break;
case SO_RCVTIMEO:
case SO_SNDTIMEO:
setSoTimeout(channel, value);
break;
// can't set these
case SO_TYPE:
case SO_RCVLOWAT:
case SO_SNDLOWAT:
case SO_DEBUG:
case SO_ERROR:
case SO_DONTROUTE:
case SO_TIMESTAMP:
}
}
private static boolean asBoolean(int value) {
return value == 0 ? false : true;
}
private SocketType(Sock sock) {
this.sock = sock;
}
private final Sock sock;
}