зеркало из https://github.com/mono/ikvm-fork.git
Reduced the number of DatagramChannelImpl differences.
This commit is contained in:
Родитель
eaaccdd4e9
Коммит
88989f0239
|
@ -43,12 +43,6 @@ class DatagramChannelImpl
|
||||||
extends DatagramChannel
|
extends DatagramChannel
|
||||||
implements SelChImpl
|
implements SelChImpl
|
||||||
{
|
{
|
||||||
// Windows 2000 introduced a "feature" that causes it to return WSAECONNRESET from receive,
|
|
||||||
// if a previous send resulted in an ICMP port unreachable. We disable this feature by using
|
|
||||||
// this ioctl.
|
|
||||||
private static final int IOC_IN = (int)0x80000000;
|
|
||||||
private static final int IOC_VENDOR = 0x18000000;
|
|
||||||
private static final int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
|
||||||
|
|
||||||
// Used to make native read and write calls
|
// Used to make native read and write calls
|
||||||
private static NativeDispatcher nd = new SocketDispatcher();
|
private static NativeDispatcher nd = new SocketDispatcher();
|
||||||
|
@ -115,15 +109,6 @@ class DatagramChannelImpl
|
||||||
this.fd = Net.socket(family, false);
|
this.fd = Net.socket(family, false);
|
||||||
this.fdVal = IOUtil.fdVal(fd);
|
this.fdVal = IOUtil.fdVal(fd);
|
||||||
this.state = ST_UNCONNECTED;
|
this.state = ST_UNCONNECTED;
|
||||||
try
|
|
||||||
{
|
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
|
||||||
fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
|
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
|
||||||
{
|
|
||||||
throw SocketUtil.convertSocketExceptionToIOException(x);
|
|
||||||
}
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ResourceManager.afterUdpClose();
|
ResourceManager.afterUdpClose();
|
||||||
throw ioe;
|
throw ioe;
|
||||||
|
@ -151,15 +136,6 @@ class DatagramChannelImpl
|
||||||
this.fd = Net.socket(family, false);
|
this.fd = Net.socket(family, false);
|
||||||
this.fdVal = IOUtil.fdVal(fd);
|
this.fdVal = IOUtil.fdVal(fd);
|
||||||
this.state = ST_UNCONNECTED;
|
this.state = ST_UNCONNECTED;
|
||||||
try
|
|
||||||
{
|
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
|
||||||
fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
|
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
|
||||||
{
|
|
||||||
throw SocketUtil.convertSocketExceptionToIOException(x);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
|
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
|
||||||
|
@ -337,7 +313,7 @@ class DatagramChannelImpl
|
||||||
throw new ClosedChannelException();
|
throw new ClosedChannelException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAddress sender; // Set by receive0 (## ugh)
|
SocketAddress sender; // Set by receive0 (## ugh)
|
||||||
|
|
||||||
public SocketAddress receive(ByteBuffer dst) throws IOException {
|
public SocketAddress receive(ByteBuffer dst) throws IOException {
|
||||||
if (dst.isReadOnly())
|
if (dst.isReadOnly())
|
||||||
|
@ -359,7 +335,7 @@ class DatagramChannelImpl
|
||||||
readerThread = NativeThread.current();
|
readerThread = NativeThread.current();
|
||||||
if (isConnected() || (security == null)) {
|
if (isConnected() || (security == null)) {
|
||||||
do {
|
do {
|
||||||
n = receive0(dst);
|
n = receive(fd, dst);
|
||||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||||
if (n == IOStatus.UNAVAILABLE)
|
if (n == IOStatus.UNAVAILABLE)
|
||||||
return null;
|
return null;
|
||||||
|
@ -367,7 +343,7 @@ class DatagramChannelImpl
|
||||||
bb = ByteBuffer.allocate(dst.remaining());
|
bb = ByteBuffer.allocate(dst.remaining());
|
||||||
for (;;) {
|
for (;;) {
|
||||||
do {
|
do {
|
||||||
n = receive0(bb);
|
n = receive(fd, bb);
|
||||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||||
if (n == IOStatus.UNAVAILABLE)
|
if (n == IOStatus.UNAVAILABLE)
|
||||||
return null;
|
return null;
|
||||||
|
@ -396,6 +372,42 @@ class DatagramChannelImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int receive(FileDescriptor fd, ByteBuffer dst)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
int pos = dst.position();
|
||||||
|
int lim = dst.limit();
|
||||||
|
assert (pos <= lim);
|
||||||
|
int rem = (pos <= lim ? lim - pos : 0);
|
||||||
|
if (dst.hasArray() && rem > 0)
|
||||||
|
return receiveIntoManagedBuffer(fd, dst, rem, pos);
|
||||||
|
|
||||||
|
// Substitute a managed buffer. If the supplied buffer is empty
|
||||||
|
// we must instead use a nonempty buffer, otherwise the call
|
||||||
|
// will not block waiting for a datagram on some platforms.
|
||||||
|
int newSize = Math.max(rem, 1);
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(newSize);
|
||||||
|
try {
|
||||||
|
int n = receiveIntoManagedBuffer(fd, bb, newSize, 0);
|
||||||
|
bb.flip();
|
||||||
|
if (n > 0 && rem > 0)
|
||||||
|
dst.put(bb);
|
||||||
|
return n;
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int receiveIntoManagedBuffer(FileDescriptor fd, ByteBuffer bb,
|
||||||
|
int rem, int pos)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
int n = receive0(fd, bb.array(), bb.arrayOffset() + pos, rem,
|
||||||
|
isConnected());
|
||||||
|
if (n > 0)
|
||||||
|
bb.position(pos + n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
public int send(ByteBuffer src, SocketAddress target)
|
public int send(ByteBuffer src, SocketAddress target)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
@ -437,7 +449,7 @@ class DatagramChannelImpl
|
||||||
return 0;
|
return 0;
|
||||||
writerThread = NativeThread.current();
|
writerThread = NativeThread.current();
|
||||||
do {
|
do {
|
||||||
n = sendImpl(src, isa);
|
n = send(fd, src, target);
|
||||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||||
|
|
||||||
synchronized (stateLock) {
|
synchronized (stateLock) {
|
||||||
|
@ -454,6 +466,52 @@ class DatagramChannelImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
if (src.hasArray())
|
||||||
|
return sendFromManagedBuffer(fd, src, target);
|
||||||
|
|
||||||
|
// Substitute a managed buffer
|
||||||
|
int pos = src.position();
|
||||||
|
int lim = src.limit();
|
||||||
|
assert (pos <= lim);
|
||||||
|
int rem = (pos <= lim ? lim - pos : 0);
|
||||||
|
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(rem);
|
||||||
|
try {
|
||||||
|
bb.put(src);
|
||||||
|
bb.flip();
|
||||||
|
// Do not update src until we see how many bytes were written
|
||||||
|
src.position(pos);
|
||||||
|
|
||||||
|
int n = sendFromManagedBuffer(fd, bb, target);
|
||||||
|
if (n > 0) {
|
||||||
|
// now update src
|
||||||
|
src.position(pos + n);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sendFromManagedBuffer(FileDescriptor fd, ByteBuffer bb,
|
||||||
|
SocketAddress target)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
int pos = bb.position();
|
||||||
|
int lim = bb.limit();
|
||||||
|
assert (pos <= lim);
|
||||||
|
int rem = (pos <= lim ? lim - pos : 0);
|
||||||
|
|
||||||
|
boolean preferIPv6 = (family != StandardProtocolFamily.INET);
|
||||||
|
int written = send0(preferIPv6, fd, bb.array(), bb.arrayOffset() + pos,
|
||||||
|
rem, target);
|
||||||
|
if (written > 0)
|
||||||
|
bb.position(pos + written);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
public int read(ByteBuffer buf) throws IOException {
|
public int read(ByteBuffer buf) throws IOException {
|
||||||
if (buf == null)
|
if (buf == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
@ -642,21 +700,12 @@ class DatagramChannelImpl
|
||||||
if (sm != null)
|
if (sm != null)
|
||||||
sm.checkConnect(isa.getAddress().getHostAddress(),
|
sm.checkConnect(isa.getAddress().getHostAddress(),
|
||||||
isa.getPort());
|
isa.getPort());
|
||||||
try
|
int n = Net.connect(family,
|
||||||
{
|
fd,
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
isa.getAddress(),
|
||||||
if (false) throw new cli.System.ObjectDisposedException("");
|
isa.getPort());
|
||||||
fd.getSocket().Connect(SocketUtil.getAddressFromInetAddress(isa.getAddress()), isa.getPort());
|
if (n <= 0)
|
||||||
fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 1 }, null);
|
throw new Error(); // Can't happen
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
|
||||||
{
|
|
||||||
throw new SocketException(x.getMessage());
|
|
||||||
}
|
|
||||||
catch (cli.System.ObjectDisposedException x1)
|
|
||||||
{
|
|
||||||
throw new SocketException("Socket is closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connection succeeded; disallow further invocation
|
// Connection succeeded; disallow further invocation
|
||||||
state = ST_CONNECTED;
|
state = ST_CONNECTED;
|
||||||
|
@ -1010,131 +1059,22 @@ class DatagramChannelImpl
|
||||||
|
|
||||||
// -- Native methods --
|
// -- Native methods --
|
||||||
|
|
||||||
private static void disconnect0(FileDescriptor fd) throws IOException
|
private static native void initIDs();
|
||||||
{
|
|
||||||
try
|
private static native void disconnect0(FileDescriptor fd)
|
||||||
{
|
throws IOException;
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
|
||||||
if (false) throw new cli.System.ObjectDisposedException("");
|
private native int receive0(FileDescriptor fd, byte[] buf, int pos, int len,
|
||||||
fd.getSocket().Connect(new cli.System.Net.IPEndPoint(cli.System.Net.IPAddress.Any, 0));
|
boolean connected)
|
||||||
fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
|
throws IOException;
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
private native int send0(boolean preferIPv6, FileDescriptor fd, byte[] buf, int pos, int len,
|
||||||
{
|
SocketAddress sa)
|
||||||
throw SocketUtil.convertSocketExceptionToIOException(x);
|
throws IOException;
|
||||||
}
|
|
||||||
catch (cli.System.ObjectDisposedException x1)
|
static {
|
||||||
{
|
Util.load();
|
||||||
throw new SocketException("Socket is closed");
|
initIDs();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int receive0(ByteBuffer bb) throws IOException
|
|
||||||
{
|
|
||||||
byte[] buf = new byte[bb.remaining()];
|
|
||||||
cli.System.Net.EndPoint[] remoteEP = new cli.System.Net.EndPoint[]
|
|
||||||
{
|
|
||||||
new cli.System.Net.IPEndPoint(0, 0)
|
|
||||||
};
|
|
||||||
InetSocketAddress addr;
|
|
||||||
int length;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (; ; )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
|
||||||
if (false) throw new cli.System.ObjectDisposedException("");
|
|
||||||
length = fd.getSocket().ReceiveFrom(buf, 0, buf.length, cli.System.Net.Sockets.SocketFlags.wrap(cli.System.Net.Sockets.SocketFlags.None), remoteEP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
|
||||||
{
|
|
||||||
if (x.get_ErrorCode() == SocketUtil.WSAECONNRESET)
|
|
||||||
{
|
|
||||||
// A previous send failed (i.e. the remote host responded with a ICMP that the port is closed) and
|
|
||||||
// the winsock stack helpfully lets us know this, but we only care about this when we're connected,
|
|
||||||
// otherwise we'll simply retry the receive (note that we use SIO_UDP_CONNRESET to prevent these
|
|
||||||
// WSAECONNRESET exceptions, but when switching from connected to disconnected, some can slip through).
|
|
||||||
if (isConnected())
|
|
||||||
{
|
|
||||||
throw new PortUnreachableException();
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (x.get_ErrorCode() == SocketUtil.WSAEMSGSIZE)
|
|
||||||
{
|
|
||||||
// The buffer size was too small for the packet, ReceiveFrom receives the part of the packet
|
|
||||||
// that fits in the buffer and then throws an exception, so we have to ignore the exception in this case.
|
|
||||||
length = buf.length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK)
|
|
||||||
{
|
|
||||||
return IOStatus.UNAVAILABLE;
|
|
||||||
}
|
|
||||||
throw SocketUtil.convertSocketExceptionToIOException(x);
|
|
||||||
}
|
|
||||||
catch (cli.System.ObjectDisposedException x1)
|
|
||||||
{
|
|
||||||
throw new SocketException("Socket is closed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cli.System.Net.IPEndPoint ep = (cli.System.Net.IPEndPoint)remoteEP[0];
|
|
||||||
addr = new InetSocketAddress(SocketUtil.getInetAddressFromIPEndPoint(ep), ep.get_Port());
|
|
||||||
} while (remoteAddress != null && !addr.equals(remoteAddress));
|
|
||||||
sender = addr;
|
|
||||||
bb.put(buf, 0, length);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int sendImpl(ByteBuffer bb, InetSocketAddress addr) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (false) throw new cli.System.Net.Sockets.SocketException();
|
|
||||||
if (false) throw new cli.System.ObjectDisposedException("");
|
|
||||||
int position = bb.position();
|
|
||||||
byte[] buf;
|
|
||||||
int offset;
|
|
||||||
int length;
|
|
||||||
if (bb.hasArray())
|
|
||||||
{
|
|
||||||
buf = bb.array();
|
|
||||||
offset = bb.arrayOffset() + bb.position();
|
|
||||||
length = bb.remaining();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf = new byte[bb.remaining()];
|
|
||||||
offset = 0;
|
|
||||||
length = buf.length;
|
|
||||||
bb.get(buf);
|
|
||||||
bb.position(position);
|
|
||||||
}
|
|
||||||
int sent = fd.getSocket().SendTo(buf, offset, length, cli.System.Net.Sockets.SocketFlags.wrap(cli.System.Net.Sockets.SocketFlags.None), new cli.System.Net.IPEndPoint(SocketUtil.getAddressFromInetAddress(addr.getAddress()), addr.getPort()));
|
|
||||||
if (bb.hasArray())
|
|
||||||
{
|
|
||||||
bb.position(position + sent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bb.put(buf, 0, sent);
|
|
||||||
}
|
|
||||||
return sent;
|
|
||||||
}
|
|
||||||
catch (cli.System.Net.Sockets.SocketException x)
|
|
||||||
{
|
|
||||||
if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK)
|
|
||||||
{
|
|
||||||
return IOStatus.UNAVAILABLE;
|
|
||||||
}
|
|
||||||
throw SocketUtil.convertSocketExceptionToIOException(x);
|
|
||||||
}
|
|
||||||
catch (cli.System.ObjectDisposedException x1)
|
|
||||||
{
|
|
||||||
throw new SocketException("Socket is closed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,116 @@ using FileDescriptor = java.io.FileDescriptor;
|
||||||
using InetAddress = java.net.InetAddress;
|
using InetAddress = java.net.InetAddress;
|
||||||
using ByteBuffer = java.nio.ByteBuffer;
|
using ByteBuffer = java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
static class Java_sun_nio_ch_DatagramChannelImpl
|
||||||
|
{
|
||||||
|
public static void initIDs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disconnect0(FileDescriptor fd)
|
||||||
|
{
|
||||||
|
#if !FIRST_PASS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fd.getSocket().Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0));
|
||||||
|
IKVM.NativeCode.sun.nio.ch.Net.setConnectionReset(fd.getSocket(), false);
|
||||||
|
}
|
||||||
|
catch (System.Net.Sockets.SocketException x)
|
||||||
|
{
|
||||||
|
throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
throw new java.net.SocketException("Socket is closed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int receive0(object obj, FileDescriptor fd, byte[] buf, int pos, int len, bool connected)
|
||||||
|
{
|
||||||
|
#if FIRST_PASS
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
sun.nio.ch.DatagramChannelImpl impl = (sun.nio.ch.DatagramChannelImpl)obj;
|
||||||
|
java.net.SocketAddress remoteAddress = impl.remoteAddress();
|
||||||
|
System.Net.EndPoint remoteEP = new System.Net.IPEndPoint(0, 0);
|
||||||
|
java.net.InetSocketAddress addr;
|
||||||
|
int length;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
length = fd.getSocket().ReceiveFrom(buf, pos, len, System.Net.Sockets.SocketFlags.None, ref remoteEP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (System.Net.Sockets.SocketException x)
|
||||||
|
{
|
||||||
|
if (x.ErrorCode == java.net.SocketUtil.WSAECONNRESET)
|
||||||
|
{
|
||||||
|
// A previous send failed (i.e. the remote host responded with a ICMP that the port is closed) and
|
||||||
|
// the winsock stack helpfully lets us know this, but we only care about this when we're connected,
|
||||||
|
// otherwise we'll simply retry the receive (note that we use SIO_UDP_CONNRESET to prevent these
|
||||||
|
// WSAECONNRESET exceptions, but when switching from connected to disconnected, some can slip through).
|
||||||
|
if (connected)
|
||||||
|
{
|
||||||
|
throw new java.net.PortUnreachableException();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (x.ErrorCode == java.net.SocketUtil.WSAEMSGSIZE)
|
||||||
|
{
|
||||||
|
// The buffer size was too small for the packet, ReceiveFrom receives the part of the packet
|
||||||
|
// that fits in the buffer and then throws an exception, so we have to ignore the exception in this case.
|
||||||
|
length = len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK)
|
||||||
|
{
|
||||||
|
return sun.nio.ch.IOStatus.UNAVAILABLE;
|
||||||
|
}
|
||||||
|
throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
throw new java.net.SocketException("Socket is closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.Net.IPEndPoint ep = (System.Net.IPEndPoint)remoteEP;
|
||||||
|
addr = new java.net.InetSocketAddress(java.net.SocketUtil.getInetAddressFromIPEndPoint(ep), ep.Port);
|
||||||
|
} while (remoteAddress != null && !addr.equals(remoteAddress));
|
||||||
|
impl.sender = addr;
|
||||||
|
return length;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int send0(object obj, bool preferIPv6, FileDescriptor fd, byte[] buf, int pos, int len, object sa)
|
||||||
|
{
|
||||||
|
#if FIRST_PASS
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
java.net.InetSocketAddress addr = (java.net.InetSocketAddress)sa;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return fd.getSocket().SendTo(buf, pos, len, System.Net.Sockets.SocketFlags.None, new System.Net.IPEndPoint(java.net.SocketUtil.getAddressFromInetAddress(addr.getAddress()), addr.getPort()));
|
||||||
|
}
|
||||||
|
catch (System.Net.Sockets.SocketException x)
|
||||||
|
{
|
||||||
|
if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK)
|
||||||
|
{
|
||||||
|
return sun.nio.ch.IOStatus.UNAVAILABLE;
|
||||||
|
}
|
||||||
|
throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
throw new java.net.SocketException("Socket is closed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !FIRST_PASS
|
#if !FIRST_PASS
|
||||||
namespace IKVM.Internal.AsyncSocket
|
namespace IKVM.Internal.AsyncSocket
|
||||||
{
|
{
|
||||||
|
@ -620,7 +730,6 @@ namespace IKVM.NativeCode.sun.nio.ch
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FileDescriptor fd = new FileDescriptor();
|
|
||||||
System.Net.Sockets.AddressFamily addressFamily = preferIPv6
|
System.Net.Sockets.AddressFamily addressFamily = preferIPv6
|
||||||
? System.Net.Sockets.AddressFamily.InterNetworkV6
|
? System.Net.Sockets.AddressFamily.InterNetworkV6
|
||||||
: System.Net.Sockets.AddressFamily.InterNetwork;
|
: System.Net.Sockets.AddressFamily.InterNetwork;
|
||||||
|
@ -630,7 +739,19 @@ namespace IKVM.NativeCode.sun.nio.ch
|
||||||
System.Net.Sockets.ProtocolType protocolType = stream
|
System.Net.Sockets.ProtocolType protocolType = stream
|
||||||
? System.Net.Sockets.ProtocolType.Tcp
|
? System.Net.Sockets.ProtocolType.Tcp
|
||||||
: System.Net.Sockets.ProtocolType.Udp;
|
: System.Net.Sockets.ProtocolType.Udp;
|
||||||
fd.setSocket(new System.Net.Sockets.Socket(addressFamily, socketType, protocolType));
|
System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(addressFamily, socketType, protocolType);
|
||||||
|
if (preferIPv6)
|
||||||
|
{
|
||||||
|
// enable IPv4 over IPv6 sockets (note that we don't have to check for >= Vista here, because nio sockets only support IPv6 on >= Vista)
|
||||||
|
const System.Net.Sockets.SocketOptionName IPV6_V6ONLY = (System.Net.Sockets.SocketOptionName)27;
|
||||||
|
socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, IPV6_V6ONLY, 0);
|
||||||
|
}
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
setConnectionReset(socket, false);
|
||||||
|
}
|
||||||
|
FileDescriptor fd = new FileDescriptor();
|
||||||
|
fd.setSocket(socket);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
catch (System.Net.Sockets.SocketException x)
|
catch (System.Net.Sockets.SocketException x)
|
||||||
|
@ -676,6 +797,18 @@ namespace IKVM.NativeCode.sun.nio.ch
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void setConnectionReset(System.Net.Sockets.Socket socket, bool enable)
|
||||||
|
{
|
||||||
|
// Windows 2000 introduced a "feature" that causes it to return WSAECONNRESET from receive,
|
||||||
|
// if a previous send resulted in an ICMP port unreachable. For unconnected datagram sockets,
|
||||||
|
// we disable this feature by using this ioctl.
|
||||||
|
const int IOC_IN = unchecked((int)0x80000000);
|
||||||
|
const int IOC_VENDOR = 0x18000000;
|
||||||
|
const int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
||||||
|
|
||||||
|
socket.IOControl(SIO_UDP_CONNRESET, new byte[] { enable ? (byte)1 : (byte)0 }, null);
|
||||||
|
}
|
||||||
|
|
||||||
public static int connect0(bool preferIPv6, FileDescriptor fd, InetAddress remote, int remotePort)
|
public static int connect0(bool preferIPv6, FileDescriptor fd, InetAddress remote, int remotePort)
|
||||||
{
|
{
|
||||||
#if FIRST_PASS
|
#if FIRST_PASS
|
||||||
|
@ -684,9 +817,14 @@ namespace IKVM.NativeCode.sun.nio.ch
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
System.Net.IPEndPoint ep = new System.Net.IPEndPoint(global::java.net.SocketUtil.getAddressFromInetAddress(remote), remotePort);
|
System.Net.IPEndPoint ep = new System.Net.IPEndPoint(global::java.net.SocketUtil.getAddressFromInetAddress(remote), remotePort);
|
||||||
if (fd.isSocketBlocking())
|
bool datagram = fd.getSocket().SocketType == System.Net.Sockets.SocketType.Dgram;
|
||||||
|
if (datagram || fd.isSocketBlocking())
|
||||||
{
|
{
|
||||||
fd.getSocket().Connect(ep);
|
fd.getSocket().Connect(ep);
|
||||||
|
if (datagram)
|
||||||
|
{
|
||||||
|
setConnectionReset(fd.getSocket(), true);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Загрузка…
Ссылка в новой задаче