3909N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A/************************************************************************ 0N/A * PlainDatagramSocketImpl 0N/A * Returns a java.lang.Integer based on 'i' 0N/A * Returns a java.lang.Boolean based on 'b' 0N/A * Returns the fd for a PlainDatagramSocketImpl or -1 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * We need to determine if this is a 2.2 kernel. 0N/A * If this fails assume that /proc has changed and that 0N/A * this must be new /proc format and hence new kernel. 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* fdObj is the FileDescriptor field on this */ 0N/A /* fd is an int field on fdObj */ 0N/A /* intialize the local port */ 0N/A /* Now that we're a connected socket, let's extract the port number 0N/A * that the system chose for us and store it in the Socket object. 0N/A "Error getting socket name");
0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* The object's field */ 0N/A /* The packetAddress address, family and port */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Method: disconnect0 0N/A /* The object's field */ 0N/A // After disconnecting a UDP socket, Linux kernel will set 0N/A // local port to zero if the port number comes from implicit 0N/A // bind. Successive send/recv on the same socket will fail. 0N/A // So bind again with former port number here. 0N/A#
endif /* AF_INET6 */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* The object's field */ 0N/A /* arg to NET_Sendto () null in this case */ 0N/A /* When JNI-ifying the JDK's IO routines, we turned 0N/A * read's and write's of byte arrays of size greater 0N/A * than 2048 bytes into several operations of size 2048. 0N/A * This saves a malloc()/memcpy()/free() for big 0N/A * buffers. This is OK for file IO and TCP, but that 0N/A * strategy violates the semantics of a datagram protocol. 0N/A * (one big send) != (several smaller sends). So here 0N/A * we *must* alloc the buffer. Note it needn't be bigger 0N/A * than 65,536 (0xFFFF) the max size of an IP packet. 0N/A * Anything bigger should be truncated anyway. 0N/A * We may want to use a smarter allocation scheme at some 0N/A#
endif /* AF_INET6 */ 0N/A * Send the datagram. 0N/A * If we are connected it's possible that sendto will return 0N/A * ECONNREFUSED indicating that an ICMP port unreachable has 0N/A "ICMP Port Unreachable");
0N/A "operation interrupted");
0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A "operation interrupted");
0N/A return ret;
/* WARNING: SHOULD WE REALLY RETURN -2??? */ 0N/A "ICMP Port Unreachable");
0N/A "Receive timed out");
0N/A "operation interrupted");
0N/A /* When JNI-ifying the JDK's IO routines, we turned 0N/A * read's and write's of byte arrays of size greater 0N/A * than 2048 bytes into several operations of size 2048. 0N/A * This saves a malloc()/memcpy()/free() for big 0N/A * buffers. This is OK for file IO and TCP, but that 0N/A * strategy violates the semantics of a datagram protocol. 0N/A * (one big send) != (several smaller sends). So here 0N/A * we *must* alloc the buffer. Note it needn't be bigger 0N/A * than 65,536 (0xFFFF) the max size of an IP packet. 0N/A * anything bigger is truncated anyway. 0N/A * We may want to use a smarter allocation scheme at some 0N/A /* truncate the data if the packet's length is too small */ 0N/A "ICMP Port Unreachable");
0N/A "operation interrupted");
0N/A * success - fill in received address... 0N/A * REMIND: Fill in an int on the packet, and create inetadd 0N/A * object in Java, as a performance improvement. Also 0N/A * construct the inetadd object lazily. 0N/A * Check if there is an InetAddress already associated with this 0N/A * packet. If so we check if it is the same source address. We 0N/A * can't update any existing InetAddress because it is immutable 0N/A /* force a new InetAddress to be created */ 0N/A /* stuff the new Inetaddress in the packet */ 0N/A /* only get the new port number */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* When JNI-ifying the JDK's IO routines, we turned 0N/A * read's and write's of byte arrays of size greater 0N/A * than 2048 bytes into several operations of size 2048. 0N/A * This saves a malloc()/memcpy()/free() for big 0N/A * buffers. This is OK for file IO and TCP, but that 0N/A * strategy violates the semantics of a datagram protocol. 0N/A * (one big send) != (several smaller sends). So here 0N/A * we *must* alloc the buffer. Note it needn't be bigger 0N/A * than 65,536 (0xFFFF) the max size of an IP packet. 0N/A * anything bigger is truncated anyway. 0N/A * We may want to use a smarter allocation scheme at some 0N/A * On Linux with the 2.2 kernel we simulate connected datagrams by 0N/A * discarding packets 0N/A "Receive timed out");
0N/A "operation interrupted");
0N/A * Security Note: For Linux 2.2 with connected datagrams ensure that 0N/A * you receive into the stack/heap allocated buffer - do not attempt 0N/A * to receive directly into DatagramPacket's byte array. 0N/A * (ie: if the virtual machine support pinning don't use 0N/A * GetByteArrayElements or a JNI critical section and receive 0N/A * directly into the byte array) 0N/A /* truncate the data if the packet's length is too small */ 0N/A "ICMP Port Unreachable");
0N/A "operation interrupted");
0N/A * If we are connected then we know that the datagram that we have 0N/A * received is from the address that we are connected too. However 0N/A * on Linux with 2.2 kernel we have to simulate this behaviour by 0N/A * discarding any datagrams that aren't from the connected address. 0N/A * Discard the datagram as it's not from the connected 0N/A * Adjust timeout if necessary to ensure that we adhere to 0N/A * timeout semantics. 0N/A "Receive timed out");
0N/A * success - fill in received address... 0N/A * REMIND: Fill in an int on the packet, and create inetadd 0N/A * object in Java, as a performance improvement. Also 0N/A * construct the inetadd object lazily. 0N/A * Check if there is an InetAddress already associated with this 0N/A * packet. If so we check if it is the same source address. We 0N/A * can't update any existing InetAddress because it is immutable 0N/A /* force a new InetAddress to be created */ 0N/A /* stuff the new Inetaddress in the packet */ 0N/A /* only get the new port number */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Method: datagramSocketCreate 0N/A "Error creating socket");
2653N/A /* Disable IPV6_V6ONLY to ensure dual-socket support */ 0N/A * On Linux for IPv6 sockets we must set the hop limit 0N/A * to 1 to be compatible with default ttl of 1 for IPv4 sockets. 0N/A#
endif /* __linux__ */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Method: datagramSocketClose 0N/A * REMIND: PUT A LOCK AROUND THIS CODE 0N/A * Set outgoing multicast interface designated by a NetworkInterface. 0N/A * Throw exception if failed. 0N/A * Check that there is at least one address bound to this 0N/A "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
0N/A * We need an ipv4 address here 0N/A (
const char*)&
in,
sizeof(
in)) < 0) {
0N/A "Error setting socket option");
0N/A * Set outgoing multicast interface designated by a NetworkInterface. 0N/A * Throw exception if failed. 0N/A "IPV6_MULTICAST_IF failed (interface has IPv4 " 0N/A "Error setting socket option");
0N/A * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socket 0N/A * option so record index for later retrival. 0N/A * Set outgoing multicast interface designated by an InetAddress. 0N/A * Throw exception if failed. 0N/A (
const char*)&
in,
sizeof(
in)) < 0) {
0N/A "Error setting socket option");
0N/A * Set outgoing multicast interface designated by an InetAddress. 0N/A * Throw exception if failed. 0N/A "bad argument for IP_MULTICAST_IF" 0N/A ": address not bound to any interface");
0N/A * Sets the multicast interface. 0N/A * SocketOptions.IP_MULTICAST_IF :- 0N/A * value is a InetAddress 0N/A * IPv4: set outgoing multicast interface using 0N/A * IPv6: Get the index of the interface to which the 0N/A * InetAddress is bound 0N/A * Set outgoing multicast interface using 0N/A * On Linux 2.2 record interface index as can't 0N/A * query the multicast interface. 0N/A * SockOptions.IF_MULTICAST_IF2 :- 0N/A * value is a NetworkInterface 0N/A * IPv4: Obtain IP address bound to network interface 0N/A * (NetworkInterface.addres[0]) 0N/A * set outgoing multicast interface using 0N/A * IPv6: Obtain NetworkInterface.index 0N/A * Set outgoing multicast interface using 0N/A * On Linux 2.2 record interface index as can't 0N/A * query the multicast interface. 0N/A * value is an InetAddress. 5474N/A#
else /* __linux__ not defined */ 0N/A * value is a NetworkInterface. 5474N/A#
else /* __linux__ not defined */ 0N/A * Can't query IPV6_MULTICAST_LOOP on Linux 2.2 kernel so 0N/A * store it in impl so that we can simulate getsockopt. 0N/A * Sets the multicast loopback mode. 5474N/A#
else /* __linux__ not defined */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Method: socketSetOption 0N/A * Check that socket hasn't been closed 0N/A * Check argument has been provided 0N/A * Setting the multicast interface handled seperately 0N/A * Setting the multicast loopback mode handled separately 0N/A * Map the Java level socket option to the platform specific 0N/A * level and option name. 0N/A /* SO_REUSEADDR or SO_BROADCAST */ 0N/A "Socket option not supported by PlainDatagramSocketImp");
0N/A * Return the multicast interface: 0N/A * SocketOptions.IP_MULTICAST_IF 0N/A * Create InetAddress 0N/A * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 0N/A * kernel but struct in_addr on 2.4 kernel 0N/A * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or 0N/A * obtain from impl is Linux 2.2 kernel 0N/A * If index == 0 return InetAddress representing 0N/A * If index > 0 query NetworkInterface by index 0N/A * and returns addrs[0] 0N/A * SocketOptions.IP_MULTICAST_IF2 0N/A * Query NetworkInterface by IP address and 0N/A * return the NetworkInterface that the address 0N/A * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF 0N/A * (except Linux .2 kernel) 0N/A * Query NetworkInterface by index and 0N/A * return NetworkInterface. 0N/A * IPv4 implementation 0N/A "Error getting socket option");
0N/A * Construct and populate an Inet4Address 0N/A * For IP_MULTICAST_IF return InetAddress 0N/A * For IP_MULTICAST_IF2 we get the NetworkInterface for 0N/A * this address and return it 0N/A * The address doesn't appear to be bound at any known 0N/A * NetworkInterface. Therefore we construct a NetworkInterface 0N/A * with this address. 0N/A * IPv6 implementation 0N/A * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socke option 0N/A * so use cached index. 0N/A "Error getting socket option");
0N/A * If multicast to a specific interface then return the 0N/A * interface (for IF2) or the any address on that interface 0N/A "IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
0N/A * For IP_MULTICAST_IF2 return the NetworkInterface 0N/A * For IP_MULTICAST_IF return addrs[0] 0N/A "IPV6_MULTICAST_IF returned interface without IP bindings");
0N/A * Multicast to any address - return anyLocalAddress 0N/A * or a NetworkInterface with addrs[0] set to anyLocalAddress 0N/A * Returns relevant info as a jint. 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Method: socketGetOption 0N/A * Handle IP_MULTICAST_IF seperately 0N/A * SO_BINDADDR implemented using getsockname 0N/A /* find out local IP address */ 0N/A "Error getting socket name");
0N/A * Map the Java level socket option to the platform specific 0N/A * level and option name. 0N/A * IP_MULTICAST_LOOP socket option isn't available on Linux 2.2 0N/A * kernel with IPv6 so return value stored in impl. 0N/A "Error getting socket option");
0N/A /* getLoopbackMode() returns true if IP_MULTICAST_LOOP disabled */ 0N/A /* should never rearch here */ 0N/A * Multicast-related calls 0N/A * Set TTL for a socket. Throw exception if failed. 0N/A "Error setting socket option");
0N/A * Set hops limit for a socket. Throw exception if failed. 0N/A "Error setting socket option");
0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* it is important to cast this to a char, otherwise setsockopt gets confused */ 0N/A /* setsockopt to be correct ttl */ 5474N/A#
else /* __linux__ not defined */ 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A /* getsockopt of ttl */ 0N/A * Linux 2.2 kernel doesn't support IPV6_MULTICAST_HOPS socket option 0N/A "Error getting socket option");
0N/A#
endif /* AF_INET6 */ 0N/A "Error getting socket option");
0N/A * mcast_join_leave: Join or leave a multicast group. 0N/A * to join/leave multicast group. If multicast group is an IPv4 address then 0N/A * an IPv4-mapped address is used. 0N/A * On Linux with IPv6 if we wish to join/leave an IPv4 multicast group then 0N/A * we must use the IPv4 socket options. This is because the IPv6 socket options 0N/A * don't support IPv4-mapped addresses. This is true as per 2.2.19 and 2.4.7 0N/A * kernel releases. In the future it's possible that IP_ADD_MEMBERSHIP 0N/A * will be updated to return ENOPROTOOPT if uses with an IPv6 socket (Solaris 0N/A * already does this). Thus to cater for this we first try with the IPv4 0N/A * socket options and if they fail we use the IPv6 socket options. This 0N/A * seems a reasonable failsafe solution. 0N/A * IPv6 not compiled in 0N/A * joinGroup(InetAddress, NetworkInterface) implementation :- 0N/A * Linux/IPv6: use ip_mreqn structure populated with multicast 0N/A * address and interface index. 0N/A * IPv4: use ip_mreq structure populated with multicast 0N/A * address and first address obtained from 0N/A "bad argument for IP_ADD_MEMBERSHIP: " 0N/A "No IP addresses bound to interface");
0N/A * joinGroup(InetAddress) implementation :- 0N/A * Linux/IPv6: use ip_mreqn structure populated with multicast 0N/A * address and interface index. index obtained 0N/A * from cached value or IPV6_MULTICAST_IF. 0N/A * IPv4: use ip_mreq structure populated with multicast 0N/A * address and local address obtained from 0N/A * IP_MULTICAST_IF. On Linux IP_MULTICAST_IF 0N/A * returns different structure depending on 0N/A * Join the multicast group. 0N/A * If IP_ADD_MEMBERSHIP returns ENOPROTOOPT on Linux and we've got 0N/A * IPv6 enabled then it's possible that the kernel has been fixed 0N/A * so we switch to IPV6_ADD_MEMBERSHIP socket option. 0N/A * As of 2.4.7 kernel IPV6_ADD_MEMERSHIP can't handle IPv4-mapped 0N/A * addresses so we have to use IP_ADD_MEMERSHIP for IPv4 multicast 0N/A * groups. However if the socket is an IPv6 socket then then setsockopt 0N/A * should reurn ENOPROTOOPT. We assume this will be fixed in Linux 0N/A "Not a member of the multicast group");
0N/A * If we haven't switched to IPv6 socket option then we're done. 0N/A * IPv6 join. If it's an IPv4 multicast group then we use an IPv4-mapped 0N/A * 2.2 kernel doens't support IPV6_MULTICAST_IF socket option 0N/A * On 2.4.8+ if we join a group with the interface set to 0 0N/A * then the kernel records the interface it decides. This causes 0N/A * subsequent leave groups to fail as there is no match. Thus we 0N/A * pick the interface if there is a matching route. 0N/A /* Join the multicast group */ 0N/A "Not a member of the multicast group");
0N/A * Class: java_net_PlainDatagramSocketImpl 0N/A * Class: java_net_PlainDatagramSocketImpl