public static int connect0(FileDescriptor fd, bool preferIPv6, InetAddress remote, int remotePort, object handler) { #if FIRST_PASS return(0); #else return(new Connect().Do(fd.getSocket(), new System.Net.IPEndPoint(java.net.SocketUtil.getAddressFromInetAddress(remote, preferIPv6), remotePort), handler)); #endif }
public static int write0(FileDescriptor fd, ByteBuffer[] bufs, object handler) { #if FIRST_PASS return(0); #else return(new Send().Do(fd.getSocket(), bufs, handler)); #endif }
public static int accept0(FileDescriptor listenSocket, FileDescriptor acceptSocket, object handler) { #if FIRST_PASS return(0); #else return(new Accept().Do(listenSocket.getSocket(), acceptSocket.getSocket(), handler)); #endif }
public static void disconnect0(FileDescriptor fd, bool isIPv6) { #if !FIRST_PASS try { fd.getSocket().Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)); IKVM.NativeCode.sun.nio.ch.Net.setConnectionReset(fd.getSocket(), false); } catch (System.Net.Sockets.SocketException x) { throw java.net.SocketUtil.convertSocketExceptionToIOException(x); } catch (ObjectDisposedException) { throw new java.net.SocketException("Socket is closed"); } #endif }
public static int send0(object obj, bool preferIPv6, FileDescriptor fd, byte[] buf, int pos, int len, InetAddress addr, int port) { #if FIRST_PASS return(0); #else try { return(fd.getSocket().SendTo(buf, pos, len, System.Net.Sockets.SocketFlags.None, new System.Net.IPEndPoint(java.net.SocketUtil.getAddressFromInetAddress(addr, preferIPv6), port))); } catch (System.Net.Sockets.SocketException x) { if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK) { return(sun.nio.ch.IOStatus.UNAVAILABLE); } throw java.net.SocketUtil.convertSocketExceptionToIOException(x); } catch (ObjectDisposedException) { throw new java.net.SocketException("Socket is closed"); } #endif }
public static int receive0(object obj, FileDescriptor fd, byte[] buf, int pos, int len, bool connected) { #if FIRST_PASS return(0); #else sun.nio.ch.DatagramChannelImpl impl = (sun.nio.ch.DatagramChannelImpl)obj; java.net.SocketAddress remoteAddress = impl.remoteAddress(); System.Net.EndPoint remoteEP; if (fd.getSocket().AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { remoteEP = new System.Net.IPEndPoint(System.Net.IPAddress.IPv6Any, 0); } else { remoteEP = new System.Net.IPEndPoint(0, 0); } java.net.InetSocketAddress addr; int length; do { for (; ;) { try { length = fd.getSocket().ReceiveFrom(buf, pos, len, System.Net.Sockets.SocketFlags.None, ref remoteEP); break; } catch (System.Net.Sockets.SocketException x) { if (x.ErrorCode == java.net.SocketUtil.WSAECONNRESET) { // A previous send failed (i.e. the remote host responded with a ICMP that the port is closed) and // the winsock stack helpfully lets us know this, but we only care about this when we're connected, // otherwise we'll simply retry the receive (note that we use SIO_UDP_CONNRESET to prevent these // WSAECONNRESET exceptions, but when switching from connected to disconnected, some can slip through). if (connected) { throw new java.net.PortUnreachableException(); } continue; } if (x.ErrorCode == java.net.SocketUtil.WSAEMSGSIZE) { // The buffer size was too small for the packet, ReceiveFrom receives the part of the packet // that fits in the buffer and then throws an exception, so we have to ignore the exception in this case. length = len; break; } if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK) { return(sun.nio.ch.IOStatus.UNAVAILABLE); } throw java.net.SocketUtil.convertSocketExceptionToIOException(x); } catch (ObjectDisposedException) { throw new java.net.SocketException("Socket is closed"); } } System.Net.IPEndPoint ep = (System.Net.IPEndPoint)remoteEP; addr = new java.net.InetSocketAddress(java.net.SocketUtil.getInetAddressFromIPEndPoint(ep), ep.Port); } while (remoteAddress != null && !addr.equals(remoteAddress)); impl.sender = addr; return(length); #endif }
public static int socketRead0(object _this, java.io.FileDescriptor fd, byte[] b, int off, int len, int timeout) { #if FIRST_PASS return(0); #else // [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketInputStream.c System.Net.Sockets.Socket socket = null; int nread; if (fd == null) { throw new SocketException("socket closed"); } socket = fd.getSocket(); if (socket == null) { throw new SocketException("Socket closed"); } if (timeout != 0) { if (timeout <= 5000 || !net_util_md.isRcvTimeoutSupported) { int ret = net_util_md.NET_Timeout(socket, timeout); if (ret <= 0) { if (ret == 0) { throw new SocketTimeoutException("Read timed out"); } else { // [IKVM] the OpenJDK native code is broken and always throws this exception on any failure of NET_Timeout throw new SocketException("socket closed"); } } /*check if the socket has been closed while we were in timeout*/ if (fd.getSocket() == null) { throw new SocketException("Socket Closed"); } } } nread = Winsock.recv(socket, b, off, len, 0); if (nread > 0) { // ok } else { if (nread < 0) { /* * Recv failed. */ switch (Winsock.WSAGetLastError()) { case Winsock.WSAEINTR: throw new SocketException("socket closed"); case Winsock.WSAECONNRESET: case Winsock.WSAESHUTDOWN: /* * Connection has been reset - Windows sometimes reports * the reset as a shutdown error. */ throw new sun.net.ConnectionResetException(); case Winsock.WSAETIMEDOUT: throw new SocketTimeoutException("Read timed out"); default: throw net_util_md.NET_ThrowCurrent("recv failed"); } } } return(nread); #endif }
public static void socketWrite0(object _this, java.io.FileDescriptor fd, byte[] data, int off, int len) { #if !FIRST_PASS // [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketOutputStream.c const int MAX_BUFFER_LEN = 2048; System.Net.Sockets.Socket socket; int buflen = 65536; // MAX_HEAP_BUFFER_LEN int n; if (fd == null) { throw new SocketException("socket closed"); } else { socket = fd.getSocket(); } if (data == null) { throw new java.lang.NullPointerException("data argument"); } while (len > 0) { int loff = 0; int chunkLen = java.lang.Math.min(buflen, len); int llen = chunkLen; int retry = 0; while (llen > 0) { n = Winsock.send(socket, data, off + loff, llen, 0); if (n > 0) { llen -= n; loff += n; continue; } /* * Due to a bug in Windows Sockets (observed on NT and Windows * 2000) it may be necessary to retry the send. The issue is that * on blocking sockets send/WSASend is supposed to block if there * is insufficient buffer space available. If there are a large * number of threads blocked on write due to congestion then it's * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. * The workaround we use is to retry the send. If we have a * large buffer to send (>2k) then we retry with a maximum of * 2k buffer. If we hit the issue with <=2k buffer then we backoff * for 1 second and retry again. We repeat this up to a reasonable * limit before bailing out and throwing an exception. In load * conditions we've observed that the send will succeed after 2-3 * attempts but this depends on network buffers associated with * other sockets draining. */ if (Winsock.WSAGetLastError() == Winsock.WSAENOBUFS) { if (llen > MAX_BUFFER_LEN) { buflen = MAX_BUFFER_LEN; chunkLen = MAX_BUFFER_LEN; llen = MAX_BUFFER_LEN; continue; } if (retry >= 30) { throw new SocketException("No buffer space available - exhausted attempts to queue buffer"); } System.Threading.Thread.Sleep(1000); retry++; continue; } /* * Send failed - can be caused by close or write error. */ if (Winsock.WSAGetLastError() == Winsock.WSAENOTSOCK) { throw new SocketException("Socket closed"); } else { throw net_util_md.NET_ThrowCurrent("socket write error"); } } len -= chunkLen; off += chunkLen; } #endif }