package java.net;
import java.io.IOException;
import java.io.FileDescriptor;
import java.util.Set;
import java.util.HashSet;
import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
class PlainSocketImpl extends AbstractPlainSocketImpl
{
static {
initProto();
}
PlainSocketImpl() { }
PlainSocketImpl(FileDescriptor fd) {
this.fd = fd;
}
static final ExtendedSocketOptions extendedOptions =
ExtendedSocketOptions.getInstance();
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
if (isClosedOrPending()) {
throw new SocketException("Socket closed");
}
if (supportedOptions().contains(name)) {
if (extendedOptions.isOptionSupported(name)) {
extendedOptions.setOption(fd, name, value);
} else {
super.setOption(name, value);
}
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
@SuppressWarnings("unchecked")
protected <T> T getOption(SocketOption<T> name) throws IOException {
if (isClosedOrPending()) {
throw new SocketException("Socket closed");
}
if (supportedOptions().contains(name)) {
if (extendedOptions.isOptionSupported(name)) {
return (T) extendedOptions.getOption(fd, name);
} else {
return super.getOption(name);
}
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
protected Set<SocketOption<?>> supportedOptions() {
HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
addExtSocketOptions(ExtendedSocketOptions.options(SOCK_STREAM), options);
return options;
}
private void addExtSocketOptions(Set<SocketOption<?>> extOptions,
Set<SocketOption<?>> options) {
extOptions.forEach((option) -> {
if (option.name().equals("SO_FLOW_SLA")) {
if (getSocket() != null) {
options.add(option);
}
} else {
options.add(option);
}
});
}
protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
if (opt == SocketOptions.SO_REUSEPORT &&
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
throw new UnsupportedOperationException("unsupported option");
}
try {
socketSetOption0(opt, b, val);
} catch (SocketException se) {
if (socket == null || !socket.isConnected())
throw se;
}
}
native void socketCreate(boolean isServer) throws IOException;
native void socketConnect(InetAddress address, int port, int timeout)
throws IOException;
native void socketBind(InetAddress address, int port)
throws IOException;
native void socketListen(int count) throws IOException;
native void socketAccept(SocketImpl s) throws IOException;
native int socketAvailable() throws IOException;
native void socketClose0(boolean useDeferredClose) throws IOException;
native void socketShutdown(int howto) throws IOException;
static native void initProto();
native void socketSetOption0(int cmd, boolean on, Object value)
throws SocketException;
native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
native void socketSendUrgentData(int data) throws IOException;
}