зеркало из https://github.com/mono/ikvm-fork.git
Implemented dual stack sockets.
This commit is contained in:
Родитель
0fe529afda
Коммит
f0d18c9361
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче