< prev index next >

src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java

Print this page

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package sun.nio.ch;
 27 

 28 import java.net.Inet4Address;
 29 import java.net.Inet6Address;
 30 import java.net.InetAddress;
 31 import java.net.InetSocketAddress;
 32 import java.net.ProtocolFamily;
 33 import java.net.SocketException;
 34 import java.net.StandardProtocolFamily;
 35 import java.net.UnknownHostException;
 36 import java.nio.channels.UnsupportedAddressTypeException;
 37 



 38 import jdk.internal.access.JavaNetInetAddressAccess;
 39 import jdk.internal.access.SharedSecrets;
 40 import jdk.internal.misc.Unsafe;
 41 import jdk.internal.util.ArraysSupport;

 42 
 43 /**
 44  * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
 45  * and struct sockaddr_in6.
 46  *
 47  * This class is not thread safe.
 48  */
 49 class NativeSocketAddress {
 50     private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();
 51     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 52     private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
 53 
 54     private static final int AF_INET  = AFINET();
 55     private static final int AF_INET6 = AFINET6();
 56 
 57     private static final int SIZEOF_SOCKADDR4     = sizeofSockAddr4();
 58     private static final int SIZEOF_SOCKADDR6     = sizeofSockAddr6();
 59     private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);
 60     private static final int SIZEOF_FAMILY        = sizeofFamily();
 61     private static final int OFFSET_FAMILY        = offsetFamily();
 62     private static final int OFFSET_SIN4_PORT     = offsetSin4Port();
 63     private static final int OFFSET_SIN4_ADDR     = offsetSin4Addr();
 64     private static final int OFFSET_SIN6_PORT     = offsetSin6Port();
 65     private static final int OFFSET_SIN6_ADDR     = offsetSin6Addr();
 66     private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId();
 67     private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo();
 68 
 69     // SOCKETADDRESS
 70     private final long address;
 71 
 72     long address() {
 73         return address;
 74     }
 75 
 76     NativeSocketAddress() {
 77         long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS);
 78         UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0);
 79         this.address = base;



 80     }
 81 
 82     /**
 83      * Allocate an array of native socket addresses.
 84      */
 85     static NativeSocketAddress[] allocate(int count) {
 86         NativeSocketAddress[] array = new NativeSocketAddress[count];
 87         for (int i = 0; i < count; i++) {
 88             try {
 89                 array[i] = new NativeSocketAddress();
 90             } catch (OutOfMemoryError e) {
 91                 freeAll(array);
 92                 throw e;
 93             }
 94         }
 95         return array;
 96     }
 97 
 98     /**
 99      * Free all non-null native socket addresses in the given array.
100      */
101     static void freeAll(NativeSocketAddress[] array) {
102         for (int i = 0; i < array.length; i++) {
103             NativeSocketAddress sa = array[i];
104             if (sa != null) {
105                 UNSAFE.freeMemory(sa.address);
106             }
107         }
108     }
109 



110     /**
111      * Encodes the given InetSocketAddress into this socket address.
112      * @param protocolFamily protocol family
113      * @param isa the InetSocketAddress to encode
114      * @return the size of the socket address (sizeof sockaddr or sockaddr6)
115      * @throws UnsupportedAddressTypeException if the address type is not supported
116      */
117     int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
118         if (protocolFamily == StandardProtocolFamily.INET) {
119             // struct sockaddr
120             InetAddress ia = isa.getAddress();
121             if (!(ia instanceof Inet4Address))
122                 throw new UnsupportedAddressTypeException();
123             putFamily(AF_INET);
124             putAddress(AF_INET, ia);
125             putPort(AF_INET, isa.getPort());
126             return SIZEOF_SOCKADDR4;

127         } else {
128             // struct sockaddr6
129             putFamily(AF_INET6);
130             putAddress(AF_INET6, isa.getAddress());
131             putPort(AF_INET6, isa.getPort());
132             UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0);
133             return SIZEOF_SOCKADDR6;

134         }
135     }
136 
137     /**
138      * Return an InetSocketAddress to represent the socket address in this buffer.
139      * @throws SocketException if the socket address is not AF_INET or AF_INET6
140      */
141     InetSocketAddress decode() throws SocketException {
142         int family = family();
143         if (family != AF_INET && family != AF_INET6)
144             throw new SocketException("Socket family not recognized");
145         return new InetSocketAddress(address(family), port(family));
146     }
147 
148     /**
149      * Find a mismatch between this and another socket address
150      * @return the byte offset of the first mismatch or -1 if no mismatch
151      */
152     private int mismatch(NativeSocketAddress other) {
153         int i = ArraysSupport.vectorizedMismatch(null,
154                 this.address,
155                 null,
156                 other.address,
157                 SIZEOF_SOCKETADDRESS,
158                 ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
159         if (i >= 0)
160             return i;
161         i = SIZEOF_SOCKETADDRESS - ~i;
162         for (; i < SIZEOF_SOCKETADDRESS; i++) {
163             if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) {
164                 return i;
165             }
166         }
167         return -1;
168     }
169 
170     @Override
171     public boolean equals(Object other) {
172         if (other instanceof NativeSocketAddress) {
173             return mismatch((NativeSocketAddress) other) < 0;
174         } else {
175             return false;
176         }

177     }
178 


179     @Override
180     public int hashCode() {
181         int h = 0;
182         for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) {
183             h = 31 * h + UNSAFE.getByte(address + offset);

184         }
185         return h;
186     }
187 
188     @Override
189     public String toString() {
190         int family = family();
191         if (family == AF_INET || family == AF_INET6) {
192             return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
193                     + ", address=" + address(family) + ", port=" + port(family);
194         } else {
195             return "<unknown>";
196         }
197     }
198 
199     /**
200      * Return the value of the sa_family field.
201      */
202     private int family() {
203         if (SIZEOF_FAMILY == 1) {
204             return UNSAFE.getByte(address + OFFSET_FAMILY);
205         } else if (SIZEOF_FAMILY == 2) {
206             return UNSAFE.getShort(address + OFFSET_FAMILY);
207         } else {
208             throw new InternalError();
209         }
210     }
211 
212     /**
213      * Stores the given family in the sa_family field.
214      */
215     private void putFamily(int family) {
216         if (SIZEOF_FAMILY == 1) {
217             UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family);
218         } else if (SIZEOF_FAMILY == 2) {
219             UNSAFE.putShort(address + OFFSET_FAMILY, (short) family);
220         } else {
221             throw new InternalError();
222         }
223     }
224 
225     /**
226      * Return the value of the sin_port or sin6_port field. These fields are
227      * stored in network order.
228      */
229     private int port(int family) {
230         byte b1, b2;
231         if (family == AF_INET) {
232             b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT);
233             b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1);
234         } else {
235             b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT);
236             b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1);
237         }
238         return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2);
239     }
240 
241     /**
242      * Stores the given port number in the sin_port or sin6_port field. The
243      * port is stored in network order.
244      */
245     private void putPort(int family, int port) {
246         byte b1 = (byte) ((port >> 8) & 0xff);
247         byte b2 = (byte) ((port >> 0) & 0xff);
248         if (family == AF_INET) {
249             UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1);
250             UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2);
251         } else {
252             UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1);
253             UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2);
254         }
255     }
256 
257     /**
258      * Return an InetAddress to represent the value of the address in the
259      * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
260      * created with the sin6_scope_id in the sockaddr_in6 structure.
261      */
262     private InetAddress address(int family) {
263         int len;
264         int offset;
265         int scope_id;
266         if (family == AF_INET) {
267             len = 4;
268             offset = OFFSET_SIN4_ADDR;
269             scope_id = 0;
270         } else {
271             len = 16;
272             offset = OFFSET_SIN6_ADDR;
273             scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID);
274         }
275         byte[] bytes = new byte[len];
276         UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len);
277         try {
278             if (scope_id == 0) {
279                 return InetAddress.getByAddress(bytes);
280             } else {
281                 return Inet6Address.getByAddress(null, bytes, scope_id);






282             }
283         } catch (UnknownHostException e) {
284             throw new InternalError(e);
285         }
286     }
287 
288     /**
289      * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id
290      * fields. For IPv6 addresses, the sin6_addr will be popluated with an
291      * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address.
292      */
293     private void putAddress(int family, InetAddress ia) {
294         if (family == AF_INET) {
295             // IPv4 address
296             putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia);
297         } else {
298             int scope_id;
299             if (ia instanceof Inet4Address) {
300                 // IPv4-mapped IPv6 address
301                 UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0);
302                 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff);
303                 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff);
304                 putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia);
305                 scope_id = 0;
306             } else {
307                 // IPv6 address
308                 var inet6Address = (Inet6Address) ia;
309                 putAddress(address + OFFSET_SIN6_ADDR, inet6Address);
310                 scope_id = inet6Address.getScopeId();
311             }
312             UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id);
313         }

314     }
315 
316     private static void putAddress(long address, Inet4Address ia) {
317         int ipAddress = JNINA.addressValue(ia);
318         // network order
319         UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF));
320         UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF));
321         UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF));
322         UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF));
323     }
324 
325     private static void putAddress(long address, Inet6Address ia) {
326         byte[] bytes = JNINA.addressBytes(ia);
327         UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16);

328     }
329 
330     private static native int AFINET();
331     private static native int AFINET6();
332     private static native int sizeofSockAddr4();
333     private static native int sizeofSockAddr6();
334     private static native int sizeofFamily();
335     private static native int offsetFamily();
336     private static native int offsetSin4Port();
337     private static native int offsetSin4Addr();
338     private static native int offsetSin6Port();
339     private static native int offsetSin6Addr();
340     private static native int offsetSin6ScopeId();
341     private static native int offsetSin6FlowInfo();
342 
343     static {
344         IOUtil.load();
345     }
346 }

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package sun.nio.ch;
 27 
 28 import java.lang.invoke.VarHandle;
 29 import java.net.Inet4Address;
 30 import java.net.Inet6Address;
 31 import java.net.InetAddress;
 32 import java.net.InetSocketAddress;
 33 import java.net.ProtocolFamily;
 34 import java.net.SocketException;
 35 import java.net.StandardProtocolFamily;
 36 import java.net.UnknownHostException;
 37 import java.nio.channels.UnsupportedAddressTypeException;
 38 import jdk.incubator.foreign.MemoryAddress;
 39 import jdk.incubator.foreign.MemoryHandles;
 40 import jdk.incubator.foreign.MemoryLayouts;
 41 import jdk.incubator.foreign.MemorySegment;
 42 import jdk.internal.access.JavaNetInetAddressAccess;
 43 import jdk.internal.access.SharedSecrets;
 44 import jdk.internal.misc.Unsafe;
 45 import jdk.internal.sys.in6_h;
 46 import jdk.internal.sys.in_h;
 47 
 48 /**
 49  * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
 50  * and struct sockaddr_in6.
 51  *
 52  * This class is not thread safe.
 53  */
 54 final class NativeSocketAddress {
 55     private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();


 56 
 57     private static final int AF_INET  = AFINET();
 58     private static final int AF_INET6 = AFINET6();
 59 
 60     final long address() {
 61         return address.toRawLongValue();















 62     }
 63 
 64     private final MemorySegment segment;
 65     private final MemoryAddress address;
 66 
 67     private NativeSocketAddress() {
 68         segment = allocateNative(in6_h.Csockaddr_in6.sizeof());
 69         segment.fill((byte) 0x00);
 70         address = segment.baseAddress();
 71     }
 72 
 73     /**
 74      * Allocate an array of native socket addresses.
 75      */
 76     static final NativeSocketAddress[] allocate(int count) {
 77         NativeSocketAddress[] array = new NativeSocketAddress[count];
 78         for (int i = 0; i < count; i++) {
 79             try {
 80                 array[i] = new NativeSocketAddress();
 81             } catch (OutOfMemoryError e) {
 82                 freeAll(array);
 83                 throw e;
 84             }
 85         }
 86         return array;
 87     }
 88 
 89     /**
 90      * Free all non-null native socket addresses in the given array.
 91      */
 92     static final void freeAll(NativeSocketAddress[] array) {
 93         for (int i = 0; i < array.length; i++) {
 94             NativeSocketAddress sa = array[i];
 95             if (sa != null) {
 96                 sa.segment.close();
 97             }
 98         }
 99     }
100 
101     private static final VarHandle sin_family = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_family$VH(), int.class);
102     private static final VarHandle sin6_family = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_family$VH(), int.class);
103 
104     /**
105      * Encodes the given InetSocketAddress into this socket address.
106      * @param protocolFamily protocol family
107      * @param isa the InetSocketAddress to encode
108      * @return the size of the socket address (sizeof sockaddr or sockaddr6)
109      * @throws UnsupportedAddressTypeException if the address type is not supported
110      */
111     final int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
112         if (protocolFamily == StandardProtocolFamily.INET) {
113             // struct sockaddr
114             InetAddress ia = isa.getAddress();
115             if (!(ia instanceof Inet4Address))
116                 throw new UnsupportedAddressTypeException();
117             sin_family.set(address, AF_INET);
118             in_h.Csockaddr_in.sin_port$set(address, (short) isa.getPort());
119             in_h.Cin_addr.s_addr$set(in_h.Csockaddr_in.sin_addr$addr(address),
120                                      JNINA.addressValue((Inet4Address) ia));
121             return (int) in_h.Csockaddr_in.sizeof();
122         } else {
123             // struct sockaddr6
124             sin6_family.set(address, AF_INET6);
125             in6_h.Csockaddr_in6.sin6_port$set(address, (short) isa.getPort());
126             in6_h.Csockaddr_in6.sin6_flowinfo$set(address, 0);
127             in6_h.Csockaddr_in6.sin6_addr$addr(address).segment().copyFrom(addressAsSegment(isa.getAddress()));
128             in6_h.Csockaddr_in6.sin6_scope_id$set(address, scopeidFromAddress(isa.getAddress()));
129             return (int) in6_h.Csockaddr_in6.sizeof();
130         }
131     }
132 
133     /**
134      * Return an InetSocketAddress to represent the socket address in this buffer.
135      * @throws SocketException if the socket address is not AF_INET or AF_INET6
136      */
137     final InetSocketAddress decode() throws SocketException {
138         int family = (int) sin_family.get(address);
139         if (family != AF_INET && family != AF_INET6)
140             throw new SocketException("Socket family not recognized");
141         return new InetSocketAddress(address(family), port(family));
142     }
143 






















144     @Override
145     public boolean equals(Object other) {
146         if (!(other instanceof NativeSocketAddress))


147             return false;
148         NativeSocketAddress that = (NativeSocketAddress) other;
149         return this.segment.mismatch(that.segment) == -1;
150     }
151 
152     private static final VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class);
153 
154     @Override
155     public int hashCode() {
156         int h = 0;
157         final MemoryAddress addr = segment.baseAddress();
158         for (int i = 0 ; i < segment.byteSize() ; i++) {
159             h = 31 * h + (byte) BYTE_HANDLE.get(addr.addOffset(i));
160         }
161         return h;
162     }
163 
164     @Override
165     public String toString() {
166         int family = in_h.Csockaddr_in.sin_family$get(address);
167         if (family == AF_INET || family == AF_INET6) {
168             return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
169                     + ", address=" + address(family) + ", port=" + port(family);
170         } else {
171             return "<unknown>";
172         }
173     }
174 
175     private static final VarHandle sin_port = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_port$VH(), int.class);
176     private static final VarHandle sin6_port = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_port$VH(), int.class);























177 
178     /**
179      * Return the value of the sin_port or sin6_port field. These fields are
180      * stored in network order.
181      */
182     private final int port(int family) {


















183         if (family == AF_INET) {
184             return (int) sin_port.get(address);

185         } else {
186             return (int) sin6_port.get(address);

187         }
188     }
189 
190     /**
191      * Return an InetAddress to represent the value of the address in the
192      * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
193      * created with the sin6_scope_id in the sockaddr_in6 structure.
194      */
195     private final InetAddress address(int family) {














196         try {
197             if (family == AF_INET) {
198                 return InetAddress.getByAddress(intToByteArray(in_h.Cin_addr.s_addr$get(in_h.Csockaddr_in.sin_addr$addr(address))));
199             } else {
200                 int scope = in6_h.Csockaddr_in6.sin6_scope_id$get(address);
201                 byte[] ba = in6_h.Cin6_addr.__u6_addr$addr(in6_h.Csockaddr_in6.sin6_addr$addr(address)).segment().toByteArray();
202                 if (scope == 0) {
203                     return InetAddress.getByAddress(ba);
204                 } else {
205                     return Inet6Address.getByAddress(null, ba, scope);
206                 }
207             }
208         } catch (UnknownHostException e) {
209             throw new InternalError("should not reach here", e);
210         }
211     }
212 
213     private static final byte[] intToByteArray(int value) {
214         return new byte[] { (byte) (value >>> 24),
215                             (byte) (value >>> 16),
216                             (byte) (value >>> 8),
217                             (byte)  value};
218     }
219 
220     private static final MemorySegment addressAsSegment(InetAddress ia) {
221         return MemorySegment.ofArray(ipv6AddressBytes(ia));
222     }
223 
224     private static final byte[] ipv6AddressBytes(InetAddress ia) {
225         if (ia instanceof Inet4Address) {
226             byte[] ba = new byte[16];
227             ba[10] = (byte) 0xFF;
228             ba[11] = (byte) 0xFF;
229             int ipAddress = JNINA.addressValue((Inet4Address) ia);
230             // network order
231             ba[12] = (byte) ((ipAddress >>> 24) & 0xFF);
232             ba[13] = (byte) ((ipAddress >>> 16) & 0xFF);
233             ba[14] = (byte) ((ipAddress >>> 8)  & 0xFF);
234             ba[15] = (byte) (ipAddress          & 0xFF);
235             return ba;


236         }
237         return JNINA.addressBytes((Inet6Address) ia);
238     }
239 
240     private static final int scopeidFromAddress(InetAddress ia) {
241         if (ia instanceof Inet4Address)
242             return 0;
243         return ((Inet6Address) ia).getScopeId();



244     }
245 
246     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
247     private static final MemorySegment allocateNative(long byteSize) {
248         long base = UNSAFE.allocateMemory(byteSize);
249         return MemorySegment.ofNativeRestricted(MemoryAddress.ofLong(base), byteSize, null, () -> UNSAFE.freeMemory(base), null);
250     }
251 
252     private static native int AFINET();
253     private static native int AFINET6();










254 
255     static {
256         IOUtil.load();
257     }
258 }
< prev index next >