Implemented dual stack sockets.

This commit is contained in:
jfrijters 2011-08-25 14:31:48 +00:00
Родитель 0fe529afda
Коммит f0d18c9361
12 изменённых файлов: 546 добавлений и 391 удалений

Просмотреть файл

@ -102,6 +102,10 @@ java/lang/System.java
java/lang/Thread.java
java/lang/ThrowableHelper.java
java/lang/VMSystemProperties.java
java/net/DualStackPlainDatagramSocketImpl.java
java/net/DualStackPlainDatagramSocketImpl_c.java
java/net/DualStackPlainSocketImpl.java
java/net/DualStackPlainSocketImpl_c.java
java/net/net_util_md.java
java/net/SocketInputStream.java
java/net/SocketOutputStream.java

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2010 Jeroen Frijters
Copyright (C) 2010-2011 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -136,6 +136,7 @@ public final class Winsock
public static final int IPV6_MULTICAST_HOPS = SocketOptionName.MulticastTimeToLive;
public static final int IPV6_ADD_MEMBERSHIP = SocketOptionName.AddMembership;
public static final int IPV6_DROP_MEMBERSHIP = SocketOptionName.DropMembership;
public static final int IPV6_V6ONLY = 27;
public static final int SIO_UDP_CONNRESET = 0x9800000C;
@ -417,6 +418,10 @@ public final class Winsock
ep = new IPEndPoint(cli.System.Net.IPAddress.IPv6Any, 0);
}
}
else
{
ep = v4mapped(socket, ep);
}
if (socket.get_SocketType().Value == SocketType.Dgram)
{
// NOTE we use async connect to work around the issue that the .NET Socket class disallows sync Connect after the socket has received WSAECONNRESET
@ -440,6 +445,31 @@ public final class Winsock
}
}
private static IPEndPoint v4mapped(cli.System.Net.Sockets.Socket socket, IPEndPoint ep)
{
// when binding an IPv6 socket to an IPv4 address, we need to use a mapped v4 address
if (socket.get_AddressFamily().Value == AF_INET6 && ep.get_AddressFamily().Value == AF_INET)
{
byte[] v4 = ep.get_Address().GetAddressBytes();
if (v4[0] == 0 && v4[1] == 0 && v4[2] == 0 && v4[3] == 0)
{
return new IPEndPoint(IPAddress.IPv6Any, ep.get_Port());
}
else
{
byte[] v6 = new byte[16];
v6[10] = -1;
v6[11] = -1;
v6[12] = v4[0];
v6[13] = v4[1];
v6[14] = v4[2];
v6[15] = v4[3];
return new IPEndPoint(new IPAddress(v6), ep.get_Port());
}
}
return ep;
}
public static int bind(cli.System.Net.Sockets.Socket socket, IIPEndPointWrapper ep)
{
if (socket == null)
@ -451,7 +481,7 @@ public final class Winsock
{
if (false) throw new cli.System.Net.Sockets.SocketException();
if (false) throw new cli.System.ObjectDisposedException("");
socket.Bind(ep.get());
socket.Bind(v4mapped(socket, ep.get()));
return 0;
}
catch (cli.System.Net.Sockets.SocketException x)
@ -715,7 +745,7 @@ public final class Winsock
}
else
{
return socket.SendTo(buf, off, len, SocketFlags.wrap(flags), to.get());
return socket.SendTo(buf, off, len, SocketFlags.wrap(flags), v4mapped(socket, to.get()));
}
}
catch (cli.System.ArgumentException _)

Просмотреть файл

@ -168,7 +168,7 @@ public final class FileDescriptor {
* {@code false} otherwise.
*/
public boolean valid() {
return stream != null;
return stream != null || socket != null;
}
/**

Просмотреть файл

@ -25,9 +25,6 @@
package java.net;
import java.io.IOException;
import java.io.FileDescriptor;
import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess;
/**
* This class defines the plain DatagramSocketImpl that is used on
@ -44,20 +41,19 @@ import sun.misc.JavaIOFileDescriptorAccess;
class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
{
static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
protected void datagramSocketCreate() throws SocketException {
if (fd == null)
throw new SocketException("Socket closed");
int newfd = socketCreate(false /* v6Only */);
cli.System.Net.Sockets.Socket newfd = socketCreate(false /* v6Only */);
fdAccess.set(fd, newfd);
fd.setSocket(newfd);
}
protected synchronized void bind0(int lport, InetAddress laddr)
throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (laddr == null)
throw new NullPointerException("argument address");
@ -71,7 +67,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected synchronized int peek(InetAddress address) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("Null address in peek()");
@ -84,7 +80,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected synchronized int peekData(DatagramPacket p) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("packet");
@ -95,7 +91,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected synchronized void receive0(DatagramPacket p) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("packet");
@ -106,7 +102,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected void send(DatagramPacket p) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("null packet");
@ -119,7 +115,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected void connect0(InetAddress address, int port) throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("address");
@ -131,19 +127,19 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
if (fd == null || !fd.valid())
return; // disconnect doesn't throw any exceptions
socketDisconnect(fdAccess.get(fd));
socketDisconnect(fd.getSocket());
}
protected void datagramSocketClose() {
if (fd == null || !fd.valid())
return; // close doesn't throw any exceptions
socketClose(fdAccess.get(fd));
fdAccess.set(fd, -1);
socketClose(fd.getSocket());
fd.setSocket(null);
}
protected void socketSetOption(int opt, Object val) throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
int optionValue = 0;
@ -165,7 +161,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
protected Object socketGetOption(int opt) throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
// SO_BINDADDR is not a socket option.
if (opt == SO_BINDADDR) {
@ -225,41 +221,88 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
}
/* END Multicast specific methods */
private int checkAndReturnNativeFD() throws SocketException {
private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException {
if (fd == null || !fd.valid())
throw new SocketException("Socket closed");
return fdAccess.get(fd);
return fd.getSocket();
}
/* Native methods */
private static native void initIDs();
private static cli.System.Net.Sockets.Socket socketCreate(boolean v6Only) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainDatagramSocketImpl_c.socketCreate(env, v6Only);
env.ThrowPendingException();
return ret;
}
private static native int socketCreate(boolean v6Only);
private static void socketBind(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport)
throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketBind(env, fd, localAddress, localport);
env.ThrowPendingException();
}
private static native void socketBind(int fd, InetAddress localAddress, int localport)
throws SocketException;
private static void socketConnect(cli.System.Net.Sockets.Socket fd, InetAddress address, int port)
throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketConnect(env, fd, address, port);
env.ThrowPendingException();
}
private static native void socketConnect(int fd, InetAddress address, int port)
throws SocketException;
private static void socketDisconnect(cli.System.Net.Sockets.Socket fd) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketDisconnect(env, fd);
env.ThrowPendingException();
}
private static native void socketDisconnect(int fd);
private static void socketClose(cli.System.Net.Sockets.Socket fd) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketClose(env, fd);
env.ThrowPendingException();
}
private static native void socketClose(int fd);
private static int socketLocalPort(cli.System.Net.Sockets.Socket fd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketLocalPort(env, fd);
env.ThrowPendingException();
return ret;
}
private static native int socketLocalPort(int fd) throws SocketException;
private static Object socketLocalAddress(cli.System.Net.Sockets.Socket fd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
Object ret = DualStackPlainDatagramSocketImpl_c.socketLocalAddress(env, fd);
env.ThrowPendingException();
return ret;
}
private static native Object socketLocalAddress(int fd) throws SocketException;
private static int socketReceiveOrPeekData(cli.System.Net.Sockets.Socket fd, DatagramPacket packet,
int timeout, boolean connected, boolean peek) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketReceiveOrPeekData(env, fd, packet, timeout, connected, peek);
env.ThrowPendingException();
return ret;
}
private static native int socketReceiveOrPeekData(int fd, DatagramPacket packet,
int timeout, boolean connected, boolean peek) throws IOException;
private static void socketSend(cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length,
InetAddress address, int port, boolean connected) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketSend(env, fd, data, offset, length, address, port, connected);
env.ThrowPendingException();
}
private static native void socketSend(int fd, byte[] data, int offset, int length,
InetAddress address, int port, boolean connected) throws IOException;
private static void socketSetIntOption(cli.System.Net.Sockets.Socket fd, int cmd,
int optionValue) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketSetIntOption(env, fd, cmd, optionValue);
env.ThrowPendingException();
}
private static native void socketSetIntOption(int fd, int cmd,
int optionValue) throws SocketException;
private static native int socketGetIntOption(int fd, int cmd) throws SocketException;
private static int socketGetIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketGetIntOption(env, fd, cmd);
env.ThrowPendingException();
return ret;
}
}

Просмотреть файл

@ -22,6 +22,22 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.FileDescriptor;
import static ikvm.internal.JNI.*;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
final class DualStackPlainDatagramSocketImpl_c
{
static final int TRUE = 1;
static final int FALSE = 0;
static final int JVM_IO_ERR = -1;
static final int JVM_IO_INTR = -2;
/*
#include <windows.h>
#include <winsock2.h>
#include "jni.h"
@ -35,27 +51,26 @@
* behaviour whereby receiving a "connection reset" status resets the
* socket.
*/
static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
static boolean purgeOutstandingICMP(JNIEnv env, cli.System.Net.Sockets.Socket fd)
{
jboolean got_icmp = JNI_FALSE;
char buf[1];
fd_set tbl;
struct timeval t = { 0, 0 };
struct sockaddr_in rmtaddr;
int addrlen = sizeof(rmtaddr);
boolean got_icmp = false;
byte[] buf = new byte[1];
fd_set tbl = new fd_set();
timeval t = new timeval();
SOCKETADDRESS rmtaddr = null;
/*
* Peek at the queue to see if there is an ICMP port unreachable. If there
* is then receive it.
*/
FD_ZERO(&tbl);
FD_SET(fd, &tbl);
while(1) {
if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
FD_ZERO(tbl);
FD_SET(fd, tbl);
while(true) {
if (select(tbl, null, null, t) <= 0) {
break;
}
if (recvfrom(fd, buf, 1, MSG_PEEK,
(struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) {
rmtaddr) != JVM_IO_ERR) {
break;
}
if (WSAGetLastError() != WSAECONNRESET) {
@ -63,7 +78,7 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
break;
}
recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen);
recvfrom(fd, buf, 1, 0, rmtaddr);
got_icmp = JNI_TRUE;
}
@ -75,25 +90,25 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
* Method: socketCreate
* Signature: (Z)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate
(JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) {
int fd, rv, opt=0, t=TRUE;
DWORD x1, x2; /* ignored result codes */
static cli.System.Net.Sockets.Socket socketCreate
(JNIEnv env, boolean v6Only /*unused*/) {
cli.System.Net.Sockets.Socket fd;
int rv, opt=0, t=TRUE;
fd = (int) socket(AF_INET6, SOCK_DGRAM, 0);
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
return -1;
return null;
}
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
return -1;
return null;
}
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
//SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, t);
/* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which
* returns connection reset errors on unconnected UDP sockets (as well
@ -101,7 +116,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCrea
* when the socket is connected.
*/
t = FALSE;
WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0);
WSAIoctl(fd ,SIO_UDP_CONNRESET ,false);
return fd;
}
@ -111,18 +126,18 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCrea
* Method: socketBind
* Signature: (ILjava/net/InetAddress;I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
static void socketBind
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
int sa_len = sizeof(sa);
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = bind(fd, (struct sockaddr *)&sa, sa_len);
rv = bind(fd, sa);
if (rv == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEACCES) {
@ -137,27 +152,26 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
* Method: socketConnect
* Signature: (ILjava/net/InetAddress;I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
static void socketConnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
int sa_len = sizeof(sa);
DWORD x1, x2; /* ignored result codes */
int t = TRUE;
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = connect(fd, (struct sockaddr *)&sa, sa_len);
rv = connect(fd, sa);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "connect");
return;
}
/* see comment in socketCreate */
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
WSAIoctl(fd, SIO_UDP_CONNRESET, true);
}
/*
@ -165,18 +179,15 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConn
* Method: socketDisconnect
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisconnect
(JNIEnv *env, jclass clazz, jint fd ) {
static void socketDisconnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd ) {
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
DWORD x1, x2; /* ignored result codes */
int t = FALSE;
sa = new SOCKETADDRESS();
memset(&sa, 0, sa_len);
connect(fd, (struct sockaddr *)&sa, sa_len);
connect(fd, sa);
/* see comment in socketCreate */
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
WSAIoctl(fd, SIO_UDP_CONNRESET, false);
}
/*
@ -184,8 +195,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisc
* Method: socketClose
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose
(JNIEnv *env, jclass clazz , jint fd) {
static void socketClose
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
NET_SocketClose(fd);
}
@ -195,16 +206,16 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClos
* Method: socketLocalPort
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort
(JNIEnv *env, jclass clazz, jint fd) {
static int socketLocalPort
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
int len = sizeof(sa);
sa = new SOCKETADDRESS();
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "JVM_GetSockName");
return -1;
}
return (int) ntohs((u_short)GET_PORT(&sa));
return ntohs(GET_PORT(sa));
}
/*
@ -212,19 +223,19 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLoca
* Method: socketLocalAddress
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress
(JNIEnv *env , jclass clazz, jint fd) {
static InetAddress socketLocalAddress
(JNIEnv env , cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
int len = sizeof(sa);
jobject iaObj;
int port;
sa = new SOCKETADDRESS();
InetAddress iaObj;
int[] port = { 0 };
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return NULL;
return null;
}
iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
iaObj = NET_SockaddrToInetAddress(env, sa, port);
return iaObj;
}
@ -233,33 +244,32 @@ JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketL
* Method: socketReceiveOrPeekData
* Signature: (ILjava/net/DatagramPacket;IZZ)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketReceiveOrPeekData
(JNIEnv *env, jclass clazz, jint fd, jobject dpObj,
jint timeout, jboolean connected, jboolean peek) {
static int socketReceiveOrPeekData
(JNIEnv env, cli.System.Net.Sockets.Socket fd, DatagramPacket dpObj,
int timeout, boolean connected, boolean peek) {
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
sa = new SOCKETADDRESS();
int port, rv, flags=0;
char BUF[MAX_BUFFER_LEN];
char *fullPacket;
BOOL retry;
jlong prevTime = 0;
boolean retry;
long prevTime = 0;
jint packetBufferOffset, packetBufferLen;
jbyteArray packetBuffer;
int packetBufferOffset, packetBufferLen;
byte[] packetBuffer;
/* if we are only peeking. Called from peekData */
if (peek) {
flags = MSG_PEEK;
}
packetBuffer = (*env)->GetObjectField(env, dpObj, dp_bufID);
packetBufferOffset = (*env)->GetIntField(env, dpObj, dp_offsetID);
packetBufferLen = (*env)->GetIntField(env, dpObj, dp_bufLengthID);
packetBuffer = dpObj.buf;
packetBufferOffset = dpObj.offset;
packetBufferLen = dpObj.bufLength;
/*
if (packetBufferLen > MAX_BUFFER_LEN) {
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
* the max size of an IP packet. Anything bigger is truncated anyway.
*/
*-/
if (packetBufferLen > MAX_PACKET_LEN) {
packetBufferLen = MAX_PACKET_LEN;
}
@ -271,36 +281,34 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
} else {
fullPacket = &(BUF[0]);
}
*/
do {
retry = FALSE;
retry = false;
if (timeout) {
if (timeout != 0) {
if (prevTime == 0) {
prevTime = JVM_CurrentTimeMillis(env, 0);
}
rv = NET_Timeout(fd, timeout);
if (rv <= 0) {
if (rv == 0) {
JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException",
JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException",
"Receive timed out");
} else if (rv == JVM_IO_ERR) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Socket closed");
} else if (rv == JVM_IO_INTR) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
if (packetBufferLen > MAX_BUFFER_LEN) {
free(fullPacket);
}
return -1;
}
}
/* receive the packet */
rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
(struct sockaddr *)&sa, &sa_len);
rv = recvfrom(fd, packetBuffer, packetBufferOffset, packetBufferLen, flags,
sa);
if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
/* An icmp port unreachable - we must receive this as Windows
@ -310,29 +318,25 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
purgeOutstandingICMP(env, fd);
if (connected) {
JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException",
"ICMP Port Unreachable");
if (packetBufferLen > MAX_BUFFER_LEN)
free(fullPacket);
return -1;
} else if (timeout) {
} else if (timeout != 0) {
/* Adjust timeout */
jlong newTime = JVM_CurrentTimeMillis(env, 0);
timeout -= (jint)(newTime - prevTime);
long newTime = JVM_CurrentTimeMillis(env, 0);
timeout -= (int)(newTime - prevTime);
if (timeout <= 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"Receive timed out");
if (packetBufferLen > MAX_BUFFER_LEN)
free(fullPacket);
return -1;
}
prevTime = newTime;
}
retry = TRUE;
retry = true;
}
} while (retry);
port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&sa));
port = ntohs (GET_PORT(sa));
/* truncate the data if the packet's length is too small */
if (rv > packetBufferLen) {
@ -347,49 +351,45 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
rv = packetBufferLen;
} else {
/* failure */
(*env)->SetIntField(env, dpObj, dp_lengthID, 0);
dpObj.length = 0;
}
}
if (rv == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed");
} else if (rv == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
} else if (rv < 0) {
NET_ThrowCurrent(env, "Datagram receive failed");
} else {
jobject packetAddress;
InetAddress packetAddress;
/*
* Check if there is an InetAddress already associated with this
* packet. If so, we check if it is the same source address. We
* can't update any existing InetAddress because it is immutable
*/
packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID);
packetAddress = dpObj.address;
if (packetAddress != NULL) {
if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
if (!NET_SockaddrEqualsInetAddress(sa,
packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
packetAddress = null;
}
}
if (packetAddress == NULL) {
packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa,
&port);
int[] tmp = { port };
packetAddress = NET_SockaddrToInetAddress(sa, tmp);
port = tmp[0];
/* stuff the new Inetaddress into the packet */
(*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress);
dpObj.address = packetAddress;
}
/* populate the packet */
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, rv,
(jbyte *)fullPacket);
(*env)->SetIntField(env, dpObj, dp_portID, port);
(*env)->SetIntField(env, dpObj, dp_lengthID, rv);
dpObj.port = port;
dpObj.length = rv;
}
if (packetBufferLen > MAX_BUFFER_LEN) {
free(fullPacket);
}
return port;
}
@ -398,30 +398,27 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
* Method: socketSend
* Signature: (I[BIILjava/net/InetAddress;IZ)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
(JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
jobject iaObj, jint port, jboolean connected) {
static void socketSend
(JNIEnv env, cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length,
InetAddress iaObj, int port, boolean connected) {
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
SOCKETADDRESS *sap = &sa;
char BUF[MAX_BUFFER_LEN];
char *fullPacket;
int rv;
if (connected) {
sap = 0; /* arg to JVM_Sendto () null in this case */
sa_len = 0;
sa = null; /* arg to JVM_Sendto () null in this case */
} else {
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
sa = new SOCKETADDRESS();
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
}
/*
if (length > MAX_BUFFER_LEN) {
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
* the max size of an IP packet. Anything bigger is truncated anyway.
*/
*-/
if (length > MAX_PACKET_LEN) {
length = MAX_PACKET_LEN;
}
@ -433,22 +430,18 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
} else {
fullPacket = &(BUF[0]);
}
*/
(*env)->GetByteArrayRegion(env, data, offset, length,
(jbyte *)fullPacket);
rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len);
rv = sendto(fd, data, offset, length, 0, sa);
if (rv == SOCKET_ERROR) {
if (rv == JVM_IO_ERR) {
NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
} else if (rv == JVM_IO_INTR) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
}
if (length > MAX_BUFFER_LEN) {
free(fullPacket);
}
}
/*
@ -456,17 +449,17 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
* Method: socketSetIntOption
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
(JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) {
int level, opt;
static void socketSetIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd , int cmd, int value) {
int[] level = { 0 }, opt = { 0 };
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Invalid option");
return;
}
if (NET_SetSockOpt(fd, level, opt, (char *)&value, sizeof(value)) < 0) {
if (NET_SetSockOpt(fd, level[0], opt[0], value) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
}
}
@ -476,21 +469,21 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetI
* Method: socketGetIntOption
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption
(JNIEnv *env, jclass clazz, jint fd, jint cmd) {
int level, opt, result=0;
int result_len = sizeof(result);
static int socketGetIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) {
int[] level = { 0 }, opt = { 0 }, result = { 0 };
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Invalid option");
return -1;
}
if (NET_GetSockOpt(fd, level, opt, (void *)&result, &result_len) < 0) {
if (NET_GetSockOpt(fd, level[0], opt[0], result) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
return -1;
}
return result;
return result[0];
}
}

Просмотреть файл

@ -26,8 +26,6 @@ package java.net;
import java.io.IOException;
import java.io.FileDescriptor;
import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess;
/**
* This class defines the plain SocketImpl that is used on Windows platforms
@ -36,12 +34,11 @@ import sun.misc.JavaIOFileDescriptorAccess;
* single file descriptor.
*
* @author Chris Hegarty
* @author Jeroen Frijters
*/
class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
{
static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
public DualStackPlainSocketImpl() {}
public DualStackPlainSocketImpl(FileDescriptor fd) {
@ -52,14 +49,14 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
if (fd == null)
throw new SocketException("Socket closed");
int newfd = socket0(stream, false /*v6 Only*/);
cli.System.Net.Sockets.Socket newfd = socket0(stream, false /*v6 Only*/);
fdAccess.set(fd, newfd);
fd.setSocket(newfd);
}
void socketConnect(InetAddress address, int port, int timeout)
throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("inet address argument is null.");
@ -88,7 +85,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
void socketBind(InetAddress address, int port) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("inet address argument is null.");
@ -104,18 +101,18 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
void socketListen(int backlog) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
listen0(nativefd, backlog);
}
void socketAccept(SocketImpl s) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (s == null)
throw new NullPointerException("socket is null");
int newfd = -1;
cli.System.Net.Sockets.Socket newfd = null;
InetSocketAddress[] isaa = new InetSocketAddress[1];
if (timeout <= 0) {
newfd = accept0(nativefd, isaa);
@ -124,7 +121,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
try {
waitForNewConnection(nativefd, timeout);
newfd = accept0(nativefd, isaa);
if (newfd != -1) {
if (newfd != null) {
configureBlocking(newfd, true);
}
} finally {
@ -132,7 +129,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
}
/* Update (SocketImpl)s' fd */
fdAccess.set(s.fd, newfd);
s.fd.setSocket(newfd);
/* Update socketImpls remote port, address and localport */
InetSocketAddress isa = isaa[0];
s.port = isa.getPort();
@ -141,7 +138,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
int socketAvailable() throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
return available0(nativefd);
}
@ -152,18 +149,18 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
if (!fd.valid())
return;
close0(fdAccess.get(fd));
fdAccess.set(fd, -1);
close0(fd.getSocket());
fd.setSocket(null);
}
void socketShutdown(int howto) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
shutdown0(nativefd, howto);
}
void socketSetOption(int opt, boolean on, Object value)
throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (opt == SO_TIMEOUT) { // timeout implemented through select.
return;
@ -198,7 +195,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
// SO_BINDADDR is not a socket option.
if (opt == SO_BINDADDR) {
@ -219,58 +216,122 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
}
void socketSendUrgentData(int data) throws IOException {
int nativefd = checkAndReturnNativeFD();
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
sendOOB(nativefd, data);
}
private int checkAndReturnNativeFD() throws SocketException {
private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException {
if (fd == null || !fd.valid())
throw new SocketException("Socket closed");
return fdAccess.get(fd);
return fd.getSocket();
}
static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
static {
initIDs();
}
/* Native methods */
static native void initIDs();
static cli.System.Net.Sockets.Socket socket0(boolean stream, boolean v6Only) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.socket0(env, stream, v6Only);
env.ThrowPendingException();
return ret;
}
static native int socket0(boolean stream, boolean v6Only) throws IOException;
static void bind0(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport)
throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.bind0(env, fd, localAddress, localport);
env.ThrowPendingException();
}
static native void bind0(int fd, InetAddress localAddress, int localport)
throws IOException;
static int connect0(cli.System.Net.Sockets.Socket fd, InetAddress remote, int remotePort)
throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.connect0(env, fd, remote, remotePort);
env.ThrowPendingException();
return ret;
}
static native int connect0(int fd, InetAddress remote, int remotePort)
throws IOException;
static void waitForConnect(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.waitForConnect(env, fd, timeout);
env.ThrowPendingException();
}
static native void waitForConnect(int fd, int timeout) throws IOException;
static int localPort0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.localPort0(env, fd);
env.ThrowPendingException();
return ret;
}
static native int localPort0(int fd) throws IOException;
static void localAddress(cli.System.Net.Sockets.Socket fd, InetAddressContainer in) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.localAddress(env, fd, in);
env.ThrowPendingException();
}
static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
static void listen0(cli.System.Net.Sockets.Socket fd, int backlog) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.listen0(env, fd, backlog);
env.ThrowPendingException();
}
static native void listen0(int fd, int backlog) throws IOException;
static cli.System.Net.Sockets.Socket accept0(cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.accept0(env, fd, isaa);
env.ThrowPendingException();
return ret;
}
static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
static void waitForNewConnection(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.waitForNewConnection(env, fd, timeout);
env.ThrowPendingException();
}
static native void waitForNewConnection(int fd, int timeout) throws IOException;
static int available0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.available0(env, fd);
env.ThrowPendingException();
return ret;
}
static native int available0(int fd) throws IOException;
static void close0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.close0(env, fd);
env.ThrowPendingException();
}
static native void close0(int fd) throws IOException;
static void shutdown0(cli.System.Net.Sockets.Socket fd, int howto) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.shutdown0(env, fd, howto);
env.ThrowPendingException();
}
static native void shutdown0(int fd, int howto) throws IOException;
static void setIntOption(cli.System.Net.Sockets.Socket fd, int cmd, int optionValue) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.setIntOption(env, fd, cmd, optionValue);
env.ThrowPendingException();
}
static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
static int getIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.getIntOption(env, fd, cmd);
env.ThrowPendingException();
return ret;
}
static native int getIntOption(int fd, int cmd) throws SocketException;
static void sendOOB(cli.System.Net.Sockets.Socket fd, int data) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.sendOOB(env, fd, data);
env.ThrowPendingException();
}
static native void sendOOB(int fd, int data) throws IOException;
static native void configureBlocking(int fd, boolean blocking) throws IOException;
static void configureBlocking(cli.System.Net.Sockets.Socket fd, boolean blocking) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.configureBlocking(env, fd, blocking);
env.ThrowPendingException();
}
}

Просмотреть файл

@ -22,6 +22,21 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.FileDescriptor;
import static ikvm.internal.JNI.*;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
final class DualStackPlainSocketImpl_c
{
private static final int JVM_IO_ERR = -1;
private static final int JVM_IO_INTR = -2;
private static final int SET_BLOCKING = 0;
private static final int SET_NONBLOCKING = 1;
/*
#include <windows.h>
#include <winsock2.h>
#include "jni.h"
@ -31,14 +46,14 @@
#define SET_BLOCKING 0
#define SET_NONBLOCKING 1
static jclass isa_class; /* java.net.InetSocketAddress */
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
static jclass isa_class; /* java.net.InetSocketAddress *-/
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) *-/
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: initIDs
* Signature: ()V
*/
*-/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
(JNIEnv *env, jclass clazz) {
@ -56,22 +71,22 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
* Method: socket0
* Signature: (ZZ)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
(JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
int fd, rv, opt=0;
static cli.System.Net.Sockets.Socket socket0
(JNIEnv env, boolean stream, boolean v6Only /*unused*/) {
cli.System.Net.Sockets.Socket fd;
int rv, opt=0;
fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "create");
return -1;
return null;
}
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "create");
}
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
return fd;
}
@ -81,18 +96,18 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
* Method: bind0
* Signature: (ILjava/net/InetAddress;I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
static void bind0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
int sa_len = sizeof(sa);
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = NET_Bind(fd, (struct sockaddr *)&sa, sa_len);
rv = NET_Bind(fd, sa);
if (rv == SOCKET_ERROR)
NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind");
@ -103,24 +118,24 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
* Method: connect0
* Signature: (ILjava/net/InetAddress;I)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
static int connect0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
int sa_len = sizeof(sa);
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return -1;
}
rv = connect(fd, (struct sockaddr *)&sa, sa_len);
rv = connect(fd, sa);
if (rv == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
return java.net.DualStackPlainSocketImpl.WOULDBLOCK;
} else if (err == WSAEADDRNOTAVAIL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"ConnectException",
"connect: Address is invalid on local machine, or port is not valid on remote machine");
} else {
NET_ThrowNew(env, err, "connect");
@ -135,17 +150,17 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
* Method: waitForConnect
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
static void waitForConnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
int rv, retry;
int optlen = sizeof(rv);
fd_set wr, ex;
struct timeval t;
wr = new fd_set(); ex = new fd_set();
timeval t = new timeval();
FD_ZERO(&wr);
FD_ZERO(&ex);
FD_SET(fd, &wr);
FD_SET(fd, &ex);
FD_ZERO(wr);
FD_ZERO(ex);
FD_SET(fd, wr);
FD_SET(fd, ex);
t.tv_sec = timeout / 1000;
t.tv_usec = (timeout % 1000) * 1000;
@ -153,7 +168,7 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
* Wait for timeout, connection established or
* connection failed.
*/
rv = select(fd+1, 0, &wr, &ex, &t);
rv = select(null, wr, ex, t);
/*
* Timeout before connection is established/failed so
@ -162,7 +177,7 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
* The socket should be closed immediately by the caller.
*/
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"connect timed out");
shutdown( fd, SD_BOTH );
return;
@ -173,7 +188,7 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
* the socket will appear writable when the connect fails so we
* check for error rather than writable.
*/
if (!FD_ISSET(fd, &ex)) {
if (!FD_ISSET(fd, ex)) {
return; /* connection established */
}
@ -186,16 +201,18 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
* load conditions we attempt up to 3 times to get the error reason.
*/
for (retry=0; retry<3; retry++) {
int[] tmp = { 0 };
NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
(char*)&rv, &optlen);
if (rv) {
tmp);
rv = tmp[0];
if (rv != 0) {
break;
}
Sleep(0);
}
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Unable to establish connection");
} else {
NET_ThrowNew(env, rv, "connect");
@ -207,21 +224,21 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
* Method: localPort0
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
(JNIEnv *env, jclass clazz, jint fd) {
static int localPort0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
int len = sizeof(sa);
sa = new SOCKETADDRESS();
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
if (getsockname(fd, sa) == SOCKET_ERROR) {
if (WSAGetLastError() == WSAENOTSOCK) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Socket closed");
} else {
NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
}
return -1;
}
return (int) ntohs((u_short)GET_PORT(&sa));
return ntohs(GET_PORT(sa));
}
/*
@ -229,26 +246,20 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
* Method: localAddress
* Signature: (ILjava/net/InetAddressContainer;)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
(JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
int port;
static void localAddress
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddressContainer iaContainerObj) {
int[] port = { 0 };
SOCKETADDRESS sa;
int len = sizeof(sa);
jobject iaObj;
jclass iaContainerClass;
jfieldID iaFieldID;
sa = new SOCKETADDRESS();
InetAddress iaObj;
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return;
}
iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
CHECK_NULL(iaObj);
iaObj = NET_SockaddrToInetAddress(env, sa, port);
iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
CHECK_NULL(iaFieldID);
(*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
iaContainerObj.addr = iaObj;
}
@ -257,8 +268,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
* Method: listen0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
(JNIEnv *env, jclass clazz, jint fd, jint backlog) {
static void listen0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int backlog) {
if (listen(fd, backlog) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "listen failed");
}
@ -269,31 +280,31 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
* Method: accept0
* Signature: (I[Ljava/net/InetSocketAddress;)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
(JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
int newfd, port=0;
jobject isa;
jobject ia;
static cli.System.Net.Sockets.Socket accept0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) {
cli.System.Net.Sockets.Socket newfd;
int[] port = { 0 };
InetSocketAddress isa;
InetAddress ia;
SOCKETADDRESS sa;
int len = sizeof(sa);
sa = new SOCKETADDRESS();
memset((char *)&sa, 0, len);
newfd = accept(fd, (struct sockaddr *)&sa, &len);
newfd = accept(fd, sa);
if (newfd == INVALID_SOCKET) {
if (WSAGetLastError() == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
} else {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"socket closed");
}
return -1;
return null;
}
ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
ia = NET_SockaddrToInetAddress(env, sa, port);
isa = new InetSocketAddress(ia, port[0]);
isaa[0] = isa;
return newfd;
}
@ -303,18 +314,18 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
* Method: waitForNewConnection
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnection
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
static void waitForNewConnection
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
int rv;
rv = NET_Timeout(fd, timeout);
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"Accept timed out");
} else if (rv == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed");
} else if (rv == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
}
@ -324,15 +335,15 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnecti
* Method: available0
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0
(JNIEnv *env, jclass clazz, jint fd) {
jint available = -1;
static int available0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
int[] available = { -1 };
if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
if ((ioctlsocket(fd, FIONREAD, available)) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "socket available");
}
return available;
return available[0];
}
/*
@ -340,8 +351,8 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0
* Method: close0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0
(JNIEnv *env, jclass clazz, jint fd) {
static void close0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
NET_SocketClose(fd);
}
@ -350,8 +361,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0
* Method: shutdown0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
(JNIEnv *env, jclass clazz, jint fd, jint howto) {
static void shutdown0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int howto) {
shutdown(fd, howto);
}
@ -361,37 +372,36 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
* Method: setIntOption
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
(JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value) {
static void setIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd, int value) {
int level, opt;
struct linger linger;
char *parg;
int arglen;
int[] level = { 0 };
int[] opt = { 0 };
linger linger;
Object optval;
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env,
JNU_JAVANETPKG+"SocketException",
"Invalid option");
return;
}
if (opt == java_net_SocketOptions_SO_LINGER) {
parg = (char *)&linger;
arglen = sizeof(linger);
if (opt[0] == java.net.SocketOptions.SO_LINGER) {
linger = new linger();
if (value >= 0) {
linger.l_onoff = 1;
linger.l_linger = (unsigned short)value;
linger.l_linger = value & 0xFFFF;
} else {
linger.l_onoff = 0;
linger.l_linger = 0;
}
optval = linger;
} else {
parg = (char *)&value;
arglen = sizeof(value);
optval = value;
}
if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
if (NET_SetSockOpt(fd, level[0], opt[0], optval) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
}
}
@ -401,39 +411,39 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
* Method: getIntOption
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
(JNIEnv *env, jclass clazz, jint fd, jint cmd) {
static int getIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) {
int level, opt;
int result=0;
struct linger linger;
char *arg;
int arglen;
int[] level = { 0 };
int[] opt = { 0 };
int[] result = { 0 };
linger linger;
Object optval;
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env,
JNU_JAVANETPKG+"SocketException",
"Unsupported socket option");
return -1;
}
if (opt == java_net_SocketOptions_SO_LINGER) {
arg = (char *)&linger;
arglen = sizeof(linger);
if (opt[0] == java.net.SocketOptions.SO_LINGER) {
linger = new linger();
optval = linger;
} else {
arg = (char *)&result;
arglen = sizeof(result);
linger = null;
optval = result;
}
if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
if (NET_GetSockOpt(fd, level[0], opt[0], optval) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
return -1;
}
if (opt == java_net_SocketOptions_SO_LINGER)
return linger.l_onoff ? linger.l_linger : -1;
if (opt[0] == java.net.SocketOptions.SO_LINGER)
return linger.l_onoff != 0 ? linger.l_linger : -1;
else
return result;
return result[0];
}
@ -442,16 +452,15 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
* Method: sendOOB
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB
(JNIEnv *env, jclass clazz, jint fd, jint data) {
jint n;
unsigned char d = (unsigned char) data & 0xff;
static void sendOOB
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int data) {
int n;
n = send(fd, (char *)&data, 1, MSG_OOB);
n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB);
if (n == JVM_IO_ERR) {
NET_ThrowNew(env, WSAGetLastError(), "send");
} else if (n == JVM_IO_INTR) {
JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
JNU_ThrowByName(env, "java.io.InterruptedIOException", null);
}
}
@ -460,9 +469,9 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB
* Method: configureBlocking
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking
(JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
u_long arg;
static void configureBlocking
(JNIEnv env, cli.System.Net.Sockets.Socket fd, boolean blocking) {
int arg;
int result;
if (blocking == JNI_TRUE) {
@ -471,8 +480,9 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking
arg = SET_NONBLOCKING; // 1
}
result = ioctlsocket(fd, FIONBIO, &arg);
result = ioctlsocket(fd, FIONBIO, arg);
if (result == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
}
}
}

Просмотреть файл

@ -224,11 +224,3 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
private static final boolean runningOnMono = cli.System.Type.GetType("Mono.Runtime") != null;
}
// we don't support a dual-stack approach yet, so we simply make it an alias for the two-stacks approach
class DualStackPlainDatagramSocketImpl extends TwoStacksPlainDatagramSocketImpl {
// we need this method, because DatagramSocket uses reflection to check for this methods existance
protected int peekData(DatagramPacket p) throws IOException {
return super.peekData(p);
}
}

Просмотреть файл

@ -243,14 +243,3 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
env.ThrowPendingException();
}
}
// we don't support a dual-stack approach yet, so we simply make it an alias for the two-stacks approach
class DualStackPlainSocketImpl extends TwoStacksPlainSocketImpl
{
DualStackPlainSocketImpl() {
}
DualStackPlainSocketImpl(FileDescriptor fd) {
super(fd);
}
}

Просмотреть файл

@ -25,6 +25,7 @@
package java.net;
import java.io.FileDescriptor;
import cli.System.Net.IPAddress;
import cli.System.Net.IPEndPoint;
import static ikvm.internal.JNI.*;
@ -734,6 +735,10 @@ final class net_util_md
}
}
static InetAddress NET_SockaddrToInetAddress(JNIEnv env, SOCKETADDRESS him, int[] port) {
return NET_SockaddrToInetAddress(him, port);
}
static InetAddress NET_SockaddrToInetAddress(SOCKETADDRESS him, int[] port) {
InetAddress iaObj;
if (him.sa_family == AF_INET6) {
@ -821,4 +826,13 @@ final class net_util_md
static void Sleep(int ms) {
cli.System.Threading.Thread.Sleep(ms);
}
static cli.System.Net.Sockets.Socket NET_Socket (int domain, int type, int protocol) {
cli.System.Net.Sockets.Socket sock;
sock = socket (domain, type, protocol);
if (sock != INVALID_SOCKET) {
//SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);
}
return sock;
}
}

Просмотреть файл

@ -3760,11 +3760,22 @@ namespace IKVM.NativeCode.java
static class InetAddressImplFactory
{
// On Linux we can't bind both an IPv4 and IPv6 to the same port, so we have to disable IPv6 until we have a dual-stack implementation.
// Mono on Windows doesn't appear to support IPv6 either (Mono on Linux does).
private static readonly bool ipv6supported = Type.GetType("Mono.Runtime") == null
&& Environment.OSVersion.Platform == PlatformID.Win32NT
&& System.Net.Sockets.Socket.OSSupportsIPv6;
private static readonly bool ipv6supported = Init();
private static bool Init()
{
string env = IKVM.Internal.JVM.SafeGetEnvironmentVariable("IKVM_IPV6");
int val;
if (env != null && Int32.TryParse(env, out val))
{
return (val & 1) != 0;
}
// On Linux we can't bind both an IPv4 and IPv6 to the same port, so we have to disable IPv6 until we have a dual-stack implementation.
// Mono on Windows doesn't appear to support IPv6 either (Mono on Linux does).
return Type.GetType("Mono.Runtime") == null
&& Environment.OSVersion.Platform == PlatformID.Win32NT
&& System.Net.Sockets.Socket.OSSupportsIPv6;
}
public static bool isIPv6Supported()
{

Просмотреть файл

@ -492,9 +492,17 @@ namespace IKVM.NativeCode.sun.nio.ch
{
public static bool isIPv6Available0()
{
// we only support IPv6 on Vista and up
string env = IKVM.Internal.JVM.SafeGetEnvironmentVariable("IKVM_IPV6");
int val;
if (env != null && Int32.TryParse(env, out val))
{
return (val & 2) != 0;
}
// we only support IPv6 on Vista and up (because there is no TwoStacks nio implementation)
// (non-Windows OSses are currently not supported)
return System.Net.Sockets.Socket.OSSupportsIPv6
// Mono on Windows doesn't appear to support IPv6 either (Mono on Linux does).
return Type.GetType("Mono.Runtime") == null
&& System.Net.Sockets.Socket.OSSupportsIPv6
&& Environment.OSVersion.Platform == PlatformID.Win32NT
&& Environment.OSVersion.Version.Major >= 6;
}