package sun.nio.ch;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.DatagramSocketImpl;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketOption;
import java.net.SocketTimeoutException;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.IllegalBlockingModeException;
import java.util.Objects;
public class DatagramSocketAdaptor
extends DatagramSocket
{
private final DatagramChannelImpl dc;
private volatile int timeout;
private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
super(dummyDatagramSocket);
this.dc = dc;
}
public static DatagramSocket create(DatagramChannelImpl dc) {
try {
return new DatagramSocketAdaptor(dc);
} catch (IOException x) {
throw new Error(x);
}
}
private void connectInternal(SocketAddress remote)
throws SocketException
{
InetSocketAddress isa = Net.asInetSocketAddress(remote);
int port = isa.getPort();
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException("connect: " + port);
if (remote == null)
throw new IllegalArgumentException("connect: null address");
try {
dc.connect(remote);
} catch (ClosedChannelException e) {
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public void bind(SocketAddress local) throws SocketException {
try {
if (local == null)
local = new InetSocketAddress(0);
dc.bind(local);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public void connect(InetAddress address, int port) {
try {
connectInternal(new InetSocketAddress(address, port));
} catch (SocketException x) {
}
}
public void connect(SocketAddress remote) throws SocketException {
Objects.requireNonNull(remote, "Address can't be null");
connectInternal(remote);
}
public void disconnect() {
try {
dc.disconnect();
} catch (IOException x) {
throw new Error(x);
}
}
public boolean isBound() {
return dc.localAddress() != null;
}
public boolean isConnected() {
return dc.remoteAddress() != null;
}
public InetAddress getInetAddress() {
InetSocketAddress remote = dc.remoteAddress();
return (remote != null) ? remote.getAddress() : null;
}
public int getPort() {
InetSocketAddress remote = dc.remoteAddress();
return (remote != null) ? remote.getPort() : -1;
}
public void send(DatagramPacket p) throws IOException {
synchronized (dc.blockingLock()) {
if (!dc.isBlocking())
throw new IllegalBlockingModeException();
try {
synchronized (p) {
ByteBuffer bb = ByteBuffer.wrap(p.getData(),
p.getOffset(),
p.getLength());
if (dc.isConnected()) {
if (p.getAddress() == null) {
InetSocketAddress isa = dc.remoteAddress();
p.setPort(isa.getPort());
p.setAddress(isa.getAddress());
dc.write(bb);
} else {
dc.send(bb, p.getSocketAddress());
}
} else {
dc.send(bb, p.getSocketAddress());
}
}
} catch (IOException x) {
Net.translateException(x);
}
}
}
private SocketAddress receive(ByteBuffer bb) throws IOException {
assert Thread.holdsLock(dc.blockingLock()) && dc.isBlocking();
long to = this.timeout;
if (to == 0) {
return dc.receive(bb);
} else {
for (;;) {
if (!dc.isOpen())
throw new ClosedChannelException();
long st = System.currentTimeMillis();
if (dc.pollRead(to)) {
return dc.receive(bb);
}
to -= System.currentTimeMillis() - st;
if (to <= 0)
throw new SocketTimeoutException();
}
}
}
public void receive(DatagramPacket p) throws IOException {
synchronized (dc.blockingLock()) {
if (!dc.isBlocking())
throw new IllegalBlockingModeException();
try {
synchronized (p) {
ByteBuffer bb = ByteBuffer.wrap(p.getData(),
p.getOffset(),
p.getLength());
SocketAddress sender = receive(bb);
p.setSocketAddress(sender);
p.setLength(bb.position() - p.getOffset());
}
} catch (IOException x) {
Net.translateException(x);
}
}
}
public InetAddress getLocalAddress() {
if (isClosed())
return null;
InetSocketAddress local = dc.localAddress();
if (local == null)
local = new InetSocketAddress(0);
InetAddress result = local.getAddress();
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkConnect(result.getHostAddress(), -1);
} catch (SecurityException x) {
return new InetSocketAddress(0).getAddress();
}
}
return result;
}
public int getLocalPort() {
if (isClosed())
return -1;
try {
InetSocketAddress local = dc.localAddress();
if (local != null) {
return local.getPort();
}
} catch (Exception x) {
}
return 0;
}
public void setSoTimeout(int timeout) throws SocketException {
this.timeout = timeout;
}
public int getSoTimeout() throws SocketException {
return timeout;
}
private void setBooleanOption(SocketOption<Boolean> name, boolean value)
throws SocketException
{
try {
dc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private void setIntOption(SocketOption<Integer> name, int value)
throws SocketException
{
try {
dc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {
try {
return dc.getOption(name).booleanValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return false;
}
}
private int getIntOption(SocketOption<Integer> name) throws SocketException {
try {
return dc.getOption(name).intValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return -1;
}
}
public void setSendBufferSize(int size) throws SocketException {
if (size <= 0)
throw new IllegalArgumentException("Invalid send size");
setIntOption(StandardSocketOptions.SO_SNDBUF, size);
}
public int getSendBufferSize() throws SocketException {
return getIntOption(StandardSocketOptions.SO_SNDBUF);
}
public void setReceiveBufferSize(int size) throws SocketException {
if (size <= 0)
throw new IllegalArgumentException("Invalid receive size");
setIntOption(StandardSocketOptions.SO_RCVBUF, size);
}
public int getReceiveBufferSize() throws SocketException {
return getIntOption(StandardSocketOptions.SO_RCVBUF);
}
public void setReuseAddress(boolean on) throws SocketException {
setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);
}
public boolean getReuseAddress() throws SocketException {
return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);
}
public void setBroadcast(boolean on) throws SocketException {
setBooleanOption(StandardSocketOptions.SO_BROADCAST, on);
}
public boolean getBroadcast() throws SocketException {
return getBooleanOption(StandardSocketOptions.SO_BROADCAST);
}
public void setTrafficClass(int tc) throws SocketException {
setIntOption(StandardSocketOptions.IP_TOS, tc);
}
public int getTrafficClass() throws SocketException {
return getIntOption(StandardSocketOptions.IP_TOS);
}
public void close() {
try {
dc.close();
} catch (IOException x) {
throw new Error(x);
}
}
public boolean isClosed() {
return !dc.isOpen();
}
public DatagramChannel getChannel() {
return dc;
}
private static final DatagramSocketImpl dummyDatagramSocket
= new DatagramSocketImpl()
{
protected void create() throws SocketException {}
protected void bind(int lport, InetAddress laddr) throws SocketException {}
protected void send(DatagramPacket p) throws IOException {}
protected int peek(InetAddress i) throws IOException { return 0; }
protected int peekData(DatagramPacket p) throws IOException { return 0; }
protected void receive(DatagramPacket p) throws IOException {}
@Deprecated
protected void setTTL(byte ttl) throws IOException {}
@Deprecated
protected byte getTTL() throws IOException { return 0; }
protected void setTimeToLive(int ttl) throws IOException {}
protected int getTimeToLive() throws IOException { return 0;}
protected void join(InetAddress inetaddr) throws IOException {}
protected void leave(InetAddress inetaddr) throws IOException {}
protected void joinGroup(SocketAddress mcastaddr,
NetworkInterface netIf) throws IOException {}
protected void leaveGroup(SocketAddress mcastaddr,
NetworkInterface netIf) throws IOException {}
protected void close() {}
public Object getOption(int optID) throws SocketException { return null;}
public void setOption(int optID, Object value) throws SocketException {}
};
}