package sun.nio.ch;
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.NetworkInterface;
import java.net.SocketOptions;
import java.nio.channels.*;
class SocketOptsImpl
implements SocketOpts
{
private boolean reuseAddressEmulated;
private boolean isReuseAddress;
static abstract class Dispatcher {
abstract int getInt(int opt) throws IOException;
abstract void setInt(int opt, int arg) throws IOException;
abstract boolean getIsBoundCondition();
}
private final Dispatcher d;
SocketOptsImpl(Dispatcher d) {
this.d = d;
}
protected boolean getBoolean(int opt) throws IOException {
return d.getInt(opt) > 0;
}
protected void setBoolean(int opt, boolean b) throws IOException {
d.setInt(opt, b ? 1 : 0);
}
protected int getInt(int opt) throws IOException {
return d.getInt(opt);
}
protected void setInt(int opt, int n) throws IOException {
d.setInt(opt, n);
}
protected NetworkInterface getNetworkInterface(int opt)
throws IOException
{
throw new UnsupportedOperationException("NYI");
}
protected void setNetworkInterface(int opt, NetworkInterface ni)
throws IOException
{
throw new UnsupportedOperationException("NYI");
}
protected void addToString(StringBuffer sb, String s) {
char c = sb.charAt(sb.length() - 1);
if ((c != '[') && (c != '='))
sb.append(' ');
sb.append(s);
}
protected void addToString(StringBuffer sb, int n) {
addToString(sb, Integer.toString(n));
}
public boolean broadcast() throws IOException {
return getBoolean(SocketOptions.SO_BROADCAST);
}
public SocketOpts broadcast(boolean b) throws IOException {
setBoolean(SocketOptions.SO_BROADCAST, b);
return this;
}
public boolean keepAlive() throws IOException {
return getBoolean(SocketOptions.SO_KEEPALIVE);
}
public SocketOpts keepAlive(boolean b) throws IOException {
setBoolean(SocketOptions.SO_KEEPALIVE, b);
return this;
}
public int linger() throws IOException {
return getInt(SocketOptions.SO_LINGER);
}
public SocketOpts linger(int n) throws IOException {
setInt(SocketOptions.SO_LINGER, n);
return this;
}
public boolean outOfBandInline() throws IOException {
return getBoolean(SocketOptions.SO_OOBINLINE);
}
public SocketOpts outOfBandInline(boolean b) throws IOException {
setBoolean(SocketOptions.SO_OOBINLINE, b);
return this;
}
public int receiveBufferSize() throws IOException {
return getInt(SocketOptions.SO_RCVBUF);
}
public SocketOpts receiveBufferSize(int n) throws IOException {
if (n <= 0)
throw new IllegalArgumentException("Invalid receive size");
setInt(SocketOptions.SO_RCVBUF, n);
return this;
}
public int sendBufferSize() throws IOException {
return getInt(SocketOptions.SO_SNDBUF);
}
public SocketOpts sendBufferSize(int n) throws IOException {
if (n <= 0)
throw new IllegalArgumentException("Invalid send size");
setInt(SocketOptions.SO_SNDBUF, n);
return this;
}
public boolean reuseAddress() throws IOException {
if (reuseAddressEmulated) {
return isReuseAddress;
}
return getBoolean(SocketOptions.SO_REUSEADDR);
}
public SocketOpts reuseAddress(boolean b) throws IOException {
if ( Net.useExclusiveBind() && d.getIsBoundCondition() ) {
reuseAddressEmulated = true;
this.isReuseAddress = b;
} else {
setBoolean(SocketOptions.SO_REUSEADDR, b);
}
return this;
}
protected void toString(StringBuffer sb) throws IOException {
int n;
if (broadcast())
addToString(sb, "broadcast");
if (keepAlive())
addToString(sb, "keepalive");
if ((n = linger()) > 0) {
addToString(sb, "linger=");
addToString(sb, n);
}
if (outOfBandInline())
addToString(sb, "oobinline");
if ((n = receiveBufferSize()) > 0) {
addToString(sb, "rcvbuf=");
addToString(sb, n);
}
if ((n = sendBufferSize()) > 0) {
addToString(sb, "sndbuf=");
addToString(sb, n);
}
if (reuseAddress())
addToString(sb, "reuseaddr");
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(this.getClass().getInterfaces()[0].getName());
sb.append('[');
int i = sb.length();
try {
toString(sb);
} catch (IOException x) {
sb.setLength(i);
sb.append("closed");
}
sb.append(']');
return sb.toString();
}
static class IP
extends SocketOptsImpl
implements SocketOpts.IP
{
IP(Dispatcher d) {
super(d);
}
public NetworkInterface multicastInterface() throws IOException {
return getNetworkInterface(SocketOptions.IP_MULTICAST_IF2);
}
public SocketOpts.IP multicastInterface(NetworkInterface ni)
throws IOException
{
setNetworkInterface(SocketOptions.IP_MULTICAST_IF2, ni);
return this;
}
public boolean multicastLoop() throws IOException {
return getBoolean(SocketOptions.IP_MULTICAST_LOOP);
}
public SocketOpts.IP multicastLoop(boolean b) throws IOException {
setBoolean(SocketOptions.IP_MULTICAST_LOOP, b);
return this;
}
public int typeOfService() throws IOException {
return getInt(SocketOptions.IP_TOS);
}
public SocketOpts.IP typeOfService(int tos) throws IOException {
setInt(SocketOptions.IP_TOS, tos);
return this;
}
protected void toString(StringBuffer sb) throws IOException {
super.toString(sb);
int n;
if ((n = typeOfService()) > 0) {
addToString(sb, "tos=");
addToString(sb, n);
}
}
public static class TCP
extends SocketOptsImpl.IP
implements SocketOpts.IP.TCP
{
TCP(Dispatcher d) {
super(d);
}
public boolean noDelay() throws IOException {
return getBoolean(SocketOptions.TCP_NODELAY);
}
public SocketOpts.IP.TCP noDelay(boolean b) throws IOException {
setBoolean(SocketOptions.TCP_NODELAY, b);
return this;
}
protected void toString(StringBuffer sb) throws IOException {
super.toString(sb);
if (noDelay())
addToString(sb, "nodelay");
}
}
}
}