/* * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.net; import java.io.FileDescriptor; import cli.System.Net.IPAddress; import cli.System.Net.IPEndPoint; import static ikvm.internal.JNI.*; import static ikvm.internal.Winsock.*; final class net_util_md { private net_util_md() { } static final int INADDR_ANY = 0; static final int IPTOS_TOS_MASK = 0x1e; static final int IPTOS_PREC_MASK = 0xe0; static boolean isRcvTimeoutSupported = true; /* * Table of Windows Sockets errors, the specific exception we * throw for the error, and the error text. * * Note that this table excludes OS dependent errors. * * Latest list of Windows Sockets errors can be found at :- * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm */ private static class WinsockError { final int errCode; final int exc; final String errString; WinsockError(int errCode, int exc, String errString) { this.errCode = errCode; this.exc = exc; this.errString = errString; } } private static final int Exception_BindException = 1; private static final int Exception_ConnectException = 2; private static final int Exception_NoRouteToHostException = 3; private static final WinsockError[] winsock_errors = { new WinsockError(WSAEACCES, 0, "Permission denied"), new WinsockError(WSAEADDRINUSE, Exception_BindException, "Address already in use"), new WinsockError(WSAEADDRNOTAVAIL, Exception_BindException, "Cannot assign requested address"), new WinsockError(WSAEAFNOSUPPORT, 0, "Address family not supported by protocol family"), new WinsockError(WSAEALREADY, 0, "Operation already in progress"), new WinsockError(WSAECONNABORTED, 0, "Software caused connection abort"), new WinsockError(WSAECONNREFUSED, Exception_ConnectException, "Connection refused"), new WinsockError(WSAECONNRESET, 0, "Connection reset by peer"), new WinsockError(WSAEDESTADDRREQ, 0, "Destination address required"), new WinsockError(WSAEFAULT, 0, "Bad address"), new WinsockError(WSAEHOSTDOWN, 0, "Host is down"), new WinsockError(WSAEHOSTUNREACH, Exception_NoRouteToHostException, "No route to host"), new WinsockError(WSAEINPROGRESS, 0, "Operation now in progress"), new WinsockError(WSAEINTR, 0, "Interrupted function call"), new WinsockError(WSAEINVAL, 0, "Invalid argument"), new WinsockError(WSAEISCONN, 0, "Socket is already connected"), new WinsockError(WSAEMFILE, 0, "Too many open files"), new WinsockError(WSAEMSGSIZE, 0, "The message is larger than the maximum supported by the underlying transport"), new WinsockError(WSAENETDOWN, 0, "Network is down"), new WinsockError(WSAENETRESET, 0, "Network dropped connection on reset"), new WinsockError(WSAENETUNREACH, 0, "Network is unreachable"), new WinsockError(WSAENOBUFS, 0, "No buffer space available (maximum connections reached?)"), new WinsockError(WSAENOPROTOOPT, 0, "Bad protocol option"), new WinsockError(WSAENOTCONN, 0, "Socket is not connected"), new WinsockError(WSAENOTSOCK, 0, "Socket operation on nonsocket"), new WinsockError(WSAEOPNOTSUPP, 0, "Operation not supported"), new WinsockError(WSAEPFNOSUPPORT, 0, "Protocol family not supported"), new WinsockError(WSAEPROCLIM, 0, "Too many processes"), new WinsockError(WSAEPROTONOSUPPORT, 0, "Protocol not supported"), new WinsockError(WSAEPROTOTYPE, 0, "Protocol wrong type for socket"), new WinsockError(WSAESHUTDOWN, 0, "Cannot send after socket shutdown"), new WinsockError(WSAESOCKTNOSUPPORT, 0, "Socket type not supported"), new WinsockError(WSAETIMEDOUT, Exception_ConnectException, "Connection timed out"), new WinsockError(WSATYPE_NOT_FOUND, 0, "Class type not found"), new WinsockError(WSAEWOULDBLOCK, 0, "Resource temporarily unavailable"), new WinsockError(WSAHOST_NOT_FOUND, 0, "Host not found"), new WinsockError(WSA_NOT_ENOUGH_MEMORY, 0, "Insufficient memory available"), new WinsockError(WSANOTINITIALISED, 0, "Successful WSAStartup not yet performed"), new WinsockError(WSANO_DATA, 0, "Valid name, no data record of requested type"), new WinsockError(WSANO_RECOVERY, 0, "This is a nonrecoverable error"), new WinsockError(WSASYSNOTREADY, 0, "Network subsystem is unavailable"), new WinsockError(WSATRY_AGAIN, 0, "Nonauthoritative host not found"), new WinsockError(WSAVERNOTSUPPORTED, 0, "Winsock.dll version out of range"), new WinsockError(WSAEDISCON, 0, "Graceful shutdown in progress"), new WinsockError(WSA_OPERATION_ABORTED, 0, "Overlapped operation aborted") }; /* * Since winsock doesn't have the equivalent of strerror(errno) * use table to lookup error text for the error. */ static SocketException NET_ThrowNew(int errorNum, String msg) { int i; int table_size = winsock_errors.length; int excP = 0; String fullMsg; if (msg == null) { msg = "no further information"; } /* * Check table for known winsock errors */ i=0; while (i < table_size) { if (errorNum == winsock_errors[i].errCode) { break; } i++; } /* * If found get pick the specific exception and error * message corresponding to this error. */ if (i < table_size) { excP = winsock_errors[i].exc; fullMsg = winsock_errors[i].errString + ": " + msg; } else { fullMsg = "Unrecognized Windows Sockets error: " + errorNum + ": " + msg; } /* * Throw SocketException if no specific exception for this * error. */ switch (excP) { case Exception_BindException: return new BindException(fullMsg); case Exception_ConnectException: return new ConnectException(fullMsg); case Exception_NoRouteToHostException: return new NoRouteToHostException(fullMsg); default: return new SocketException(fullMsg); } } static void NET_ThrowNew(JNIEnv env, int errorNum, String msg) { env.Throw(NET_ThrowNew(errorNum, msg)); } static SocketException NET_ThrowCurrent(String msg) { return NET_ThrowNew(WSAGetLastError(), msg); } static void NET_ThrowCurrent(JNIEnv env, String msg) { env.Throw(NET_ThrowCurrent(msg)); } /* * Return the default TOS value */ static int NET_GetDefaultTOS() { // we always use the "default" default... return 0; } /* * Map the Java level socket option to the platform specific * level and option name. */ private static final class sockopts { int cmd; int level; int optname; sockopts(int cmd, int level, int optname) { this.cmd = cmd; this.level = level; this.optname = optname; } } private static final sockopts opts[] = { new sockopts(SocketOptions.TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY ), new sockopts(SocketOptions.SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE ), new sockopts(SocketOptions.SO_LINGER, SOL_SOCKET, SO_LINGER ), new sockopts(SocketOptions.SO_SNDBUF, SOL_SOCKET, SO_SNDBUF ), new sockopts(SocketOptions.SO_RCVBUF, SOL_SOCKET, SO_RCVBUF ), new sockopts(SocketOptions.SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE ), new sockopts(SocketOptions.SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR ), new sockopts(SocketOptions.SO_BROADCAST, SOL_SOCKET, SO_BROADCAST ), new sockopts(SocketOptions.IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF ), new sockopts(SocketOptions.IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP ), new sockopts(SocketOptions.IP_TOS, IPPROTO_IP, IP_TOS ), }; /* call NET_MapSocketOptionV6 for the IPv6 fd only * and NET_MapSocketOption for the IPv4 fd */ static int NET_MapSocketOptionV6(int cmd, int[] level, int[] optname) { switch (cmd) { case SocketOptions.IP_MULTICAST_IF: case SocketOptions.IP_MULTICAST_IF2: level[0] = IPPROTO_IPV6; optname[0] = IPV6_MULTICAST_IF; return 0; case SocketOptions.IP_MULTICAST_LOOP: level[0] = IPPROTO_IPV6; optname[0] = IPV6_MULTICAST_LOOP; return 0; } return NET_MapSocketOption (cmd, level, optname); } static int NET_MapSocketOption(int cmd, int[] level, int[] optname) { /* * Map the Java level option to the native level */ for (int i=0; i 0 ? scope : -1); } port[0] = ntohs(him.him6.sin_port); } else { iaObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); port[0] = ntohs(him.him4.sin_port); } return iaObj; } static void NET_ThrowByNameWithLastError(JNIEnv env, String exceptionClass, String message) { JNU_ThrowByName(env, exceptionClass, "errno: " + WSAGetLastError() + ", error: " + message + "\n"); } static boolean IN_MULTICAST(int ipv4address) { return ((ipv4address >> 24) & 0xf0) == 0xe0; } static boolean IN6_IS_ADDR_MULTICAST(in6_addr address) { return (address.s6_bytes()[0] & 0xff) == 0xff; } static final class SOCKETADDRESS implements IIPEndPointWrapper { final SOCKETADDRESS him = this; final SOCKETADDRESS him4 = this; final SOCKETADDRESS him6 = this; final SOCKETADDRESS sin_addr = this; int sa_family; int sin_port; int s_addr; byte[] sin6_addr; int sin6_scope_id; public void set(IPEndPoint ep) { if (ep == null) { sa_family = 0; sin_port = 0; s_addr = 0; sin6_addr = null; sin6_scope_id = 0; } else { sa_family = ep.get_AddressFamily().Value; sin_port = htons(ep.get_Port()); if (sa_family == AF_INET) { s_addr = (int)ep.get_Address().get_Address(); sin6_addr = null; sin6_scope_id = 0; } else { s_addr = 0; IPAddress addr = ep.get_Address(); sin6_addr = addr.GetAddressBytes(); sin6_scope_id = (int)addr.get_ScopeId(); } } } public IPEndPoint get() { if (sa_family == AF_INET) { return new IPEndPoint(new IPAddress(s_addr & 0xFFFFFFFFL), ntohs(sin_port)); } else if (sa_family == AF_INET6) { IPAddress addr; if (sin6_addr == null) { addr = IPAddress.IPv6Any; } else { addr = new IPAddress(sin6_addr, sin6_scope_id & 0xFFFFFFFFL); } return new IPEndPoint(addr, ntohs(sin_port)); } else { return null; } } } static int GET_PORT(SOCKETADDRESS sockaddr) { return sockaddr.sin_port; } 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; } static int getInetAddress_addr(JNIEnv env, InetAddress iaObj) { return iaObj.address; } static int getInetAddress_family(JNIEnv env, InetAddress iaObj) { return iaObj.family; } }