1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.File;
22 import java.io.FileDescriptor;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.net.DatagramSocket;
28 import java.net.InetAddress;
29 import java.net.InetSocketAddress;
30 import java.net.ServerSocket;
31 import java.net.SocketAddress;
32 import java.net.SocketException;
33 import java.net.URI;
34 import java.nio.ByteBuffer;
35 import java.nio.charset.StandardCharsets;
36 import java.util.HashMap;
37 import java.util.Locale;
38 import java.util.Map;
39 import java.util.Objects;
40
41 import org.eclipse.jdt.annotation.NonNull;
42 import org.eclipse.jdt.annotation.Nullable;
43 import org.newsclub.net.unix.pool.ObjectPool;
44 import org.newsclub.net.unix.pool.ObjectPool.Lease;
45
46 import com.google.errorprone.annotations.Immutable;
47 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
48
49
50
51
52
53
54 @Immutable
55 @SuppressWarnings({"PMD.CouplingBetweenObjects", "PMD.CyclomaticComplexity"})
56 public abstract class AFSocketAddress extends InetSocketAddress {
57 private static final long serialVersionUID = 1L;
58
59
60
61
62
63 static final AFSocketAddress INTERNAL_DUMMY_BIND = new SentinelSocketAddress(0);
64 static final AFSocketAddress INTERNAL_DUMMY_CONNECT = new SentinelSocketAddress(1);
65 static final AFSocketAddress INTERNAL_DUMMY_DONT_CONNECT = new SentinelSocketAddress(2);
66
67 private static final int SOCKADDR_NATIVE_FAMILY_OFFSET = NativeUnixSocket.isLoaded()
68 ? NativeUnixSocket.sockAddrNativeFamilyOffset() : -1;
69
70 private static final int SOCKADDR_NATIVE_DATA_OFFSET = NativeUnixSocket.isLoaded()
71 ? NativeUnixSocket.sockAddrNativeDataOffset() : -1;
72
73 private static final int SOCKADDR_MAX_LEN = NativeUnixSocket.isLoaded()
74 ? NativeUnixSocket.sockAddrLength(0) : 256;
75
76 private static final Map<AFAddressFamily<?>, Map<Integer, Map<ByteBuffer, AFSocketAddress>>> ADDRESS_CACHE =
77 new HashMap<>();
78
79 static final ObjectPool<ByteBuffer> SOCKETADDRESS_BUFFER_TL = ObjectPool.newThreadLocalPool(
80 () -> {
81 return AFSocketAddress.newSockAddrDirectBuffer(SOCKADDR_MAX_LEN);
82 }, (o) -> {
83 o.clear();
84 return true;
85 });
86
87 private static final boolean USE_DESERIALIZATION_FOR_INIT;
88
89 static {
90 String v = System.getProperty("org.newsclub.net.unix.AFSocketAddress.deserialize", "");
91 USE_DESERIALIZATION_FOR_INIT = v.isEmpty() ? NativeLibraryLoader.isAndroid() : Boolean
92 .parseBoolean(v);
93 }
94
95
96
97
98
99 @SuppressFBWarnings("JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS")
100 private byte[] bytes;
101
102
103
104
105 @SuppressFBWarnings("JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS")
106
107 private InetAddress inetAddress = null;
108
109
110
111
112 @SuppressWarnings("PMD.ImmutableField")
113 private transient ByteBuffer nativeAddress;
114
115
116
117
118 private transient AFAddressFamily<?> addressFamily;
119
120
121
122
123
124
125
126
127
128
129 @SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
130 protected AFSocketAddress(int port, final byte[] socketAddress, Lease<ByteBuffer> nativeAddress,
131 AFAddressFamily<?> af) throws SocketException {
132
133
134
135
136
137
138
139 super(AFInetAddress.createUnresolvedHostname(socketAddress, af), port >= 0 && port <= 0xffff
140 ? port : 0);
141 initAFSocketAddress(this, port, socketAddress, nativeAddress, af);
142 }
143
144
145
146
147
148
149
150 @SuppressWarnings("PMD.UnusedFormalParameter")
151 AFSocketAddress(Class<SentinelSocketAddress> clazz, int port) {
152 super(InetAddress.getLoopbackAddress(), port);
153 this.nativeAddress = null;
154 this.bytes = new byte[0];
155 this.addressFamily = null;
156 }
157
158 @SuppressWarnings({"cast", "this-escape"})
159 private static void initAFSocketAddress(AFSocketAddress addr, int port,
160 final byte[] socketAddress, Lease<ByteBuffer> nativeAddress, AFAddressFamily<?> af)
161 throws SocketException {
162 if (socketAddress.length == 0) {
163 throw new SocketException("Illegal address length: " + socketAddress.length);
164 }
165
166 addr.nativeAddress = nativeAddress == null ? null : (ByteBuffer) (Object) nativeAddress.get()
167 .duplicate().rewind();
168 if (port < -1) {
169 throw new IllegalArgumentException("port out of range");
170 } else if (port > 0xffff) {
171 if (!NativeUnixSocket.isLoaded()) {
172 throw (SocketException) new SocketException(
173 "Cannot set SocketAddress port - junixsocket JNI library is not available").initCause(
174 NativeUnixSocket.unsupportedException());
175 }
176 NativeUnixSocket.setPort1(addr, port);
177 }
178
179 addr.bytes = socketAddress.clone();
180 addr.addressFamily = af;
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 protected static <A extends AFSocketAddress> A newDeserializedAFSocketAddress(int port,
198 final byte[] socketAddress, Lease<ByteBuffer> nativeAddress, AFAddressFamily<A> af,
199 AFSocketAddressConstructor<A> constructor) throws SocketException {
200 String hostname = AFInetAddress.createUnresolvedHostname(socketAddress, af);
201 if (hostname == null || hostname.isEmpty()) {
202 return constructor.newAFSocketAddress(port, socketAddress, nativeAddress);
203 }
204 try (ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(AFSocketAddress
205 .craftSerializedObject(af.getSocketAddressClass(), hostname, (port >= 0 && port <= 0xffff
206 ? port : 0))))) {
207 @SuppressWarnings("unchecked")
208 A addr = (A) oin.readObject();
209 initAFSocketAddress(addr, port, socketAddress, nativeAddress, af);
210 return addr;
211 } catch (SocketException e) {
212 throw e;
213 } catch (ClassNotFoundException | IOException e) {
214 throw (SocketException) new SocketException("Unexpected deserialization problem").initCause(
215 e);
216 }
217 }
218
219
220
221
222
223
224
225
226
227
228 private static byte[] craftSerializedObject(Class<? extends AFSocketAddress> className,
229 String hostname, int port) {
230 ByteBuffer bb = ByteBuffer.allocate(768);
231 bb.putShort((short) 0xaced);
232 bb.putShort((short) 5);
233 bb.put((byte) 0x73);
234 bb.put((byte) 0x72);
235
236 putShortLengthUtf8(bb, className.getName());
237 bb.putLong(1);
238 bb.putInt(0x02000078);
239 bb.put((byte) 0x72);
240
241 putShortLengthUtf8(bb, AFSocketAddress.class.getName());
242 bb.putLong(serialVersionUID);
243 bb.putInt(0x0300025B);
244 putShortLengthUtf8(bb, "bytes");
245
246 bb.putInt(0x7400025B);
247 bb.putShort((short) 0x424C);
248
249 putShortLengthUtf8(bb, "inetAddress");
250 bb.put((byte) 0x74);
251
252 putShortLengthEncodedClassName(bb, InetAddress.class);
253
254 bb.putShort((short) 0x7872);
255 putShortLengthUtf8(bb, InetSocketAddress.class.getName());
256 bb.putLong(5076001401234631237L);
257
258 bb.putInt(0x03000349);
259 putShortLengthUtf8(bb, "port");
260
261 bb.put((byte) 0x4C);
262 putShortLengthUtf8(bb, "addr");
263
264 bb.putInt(0x71007E00);
265 bb.putShort((short) 0x034C);
266 putShortLengthUtf8(bb, "hostname");
267 bb.put((byte) 0x74);
268
269 putShortLengthEncodedClassName(bb, String.class);
270
271 bb.putShort((short) 0x7872);
272 putShortLengthUtf8(bb, SocketAddress.class.getName());
273 bb.putLong(5215720748342549866L);
274
275 bb.putInt(0x02000078);
276 bb.put((byte) 0x70);
277 bb.putInt(port);
278
279 bb.putShort((short) 0x7074);
280 putShortLengthUtf8(bb, hostname);
281
282 bb.putInt(0x78707077);
283 bb.put((byte) 0x0B);
284
285 putShortLengthUtf8(bb, "undefined");
286
287 bb.put((byte) 0x78);
288 bb.flip();
289
290 byte[] buf = new byte[bb.remaining()];
291 bb.get(buf);
292 return buf;
293 }
294
295 private static void putShortLengthEncodedClassName(ByteBuffer bb, Class<?> klazz) {
296 putShortLengthUtf8(bb, "L" + klazz.getName().replace('.', '/') + ";");
297 }
298
299 private static void putShortLengthUtf8(ByteBuffer bb, String s) {
300 byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
301 bb.putShort((short) utf8.length);
302 bb.put(utf8);
303 }
304
305
306
307
308
309
310
311
312 protected static boolean isUseDeserializationForInit() {
313 return USE_DESERIALIZATION_FOR_INIT;
314 }
315
316
317
318
319
320
321 public abstract boolean hasFilename();
322
323
324
325
326
327
328
329
330
331
332 public abstract File getFile() throws FileNotFoundException;
333
334
335
336
337
338
339 public final AFAddressFamily<?> getAddressFamily() {
340 return addressFamily;
341 }
342
343
344
345
346
347
348
349
350
351 protected static final InetAddress getInetAddress(FileDescriptor fdesc, boolean peerName,
352 AFAddressFamily<?> af) {
353 if (!fdesc.valid()) {
354 return null;
355 }
356 byte[] addr = NativeUnixSocket.sockname(af.getDomain(), fdesc, peerName);
357 if (addr == null) {
358 return null;
359 }
360 return AFInetAddress.wrapAddress(addr, af);
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 protected static final <A extends AFSocketAddress> @Nullable A getSocketAddress(
375 FileDescriptor fdesc, boolean requestPeerName, int port, AFAddressFamily<A> af) {
376 if (!fdesc.valid()) {
377 return null;
378 }
379 byte[] addr = NativeUnixSocket.sockname(af.getDomain(), fdesc, requestPeerName);
380 if (addr == null) {
381 return null;
382 }
383 try {
384
385 return AFSocketAddress.unwrap(AFInetAddress.wrapAddress(addr, af), port, af);
386 } catch (SocketException e) {
387 throw new IllegalStateException(e);
388 }
389 }
390
391 static final AFSocketAddress preprocessSocketAddress(
392 Class<? extends AFSocketAddress> supportedAddressClass, SocketAddress endpoint,
393 AFSocketAddressFromHostname<?> afh) throws SocketException {
394 Objects.requireNonNull(endpoint);
395 if (endpoint instanceof SentinelSocketAddress) {
396 return (SentinelSocketAddress) endpoint;
397 }
398
399 if (!(endpoint instanceof AFSocketAddress)) {
400 if (afh != null) {
401 if (endpoint instanceof InetSocketAddress) {
402 InetSocketAddress isa = (InetSocketAddress) endpoint;
403
404 String hostname = isa.getHostString();
405 if (afh.isHostnameSupported(hostname)) {
406 try {
407 endpoint = afh.addressFromHost(hostname, isa.getPort());
408 } catch (SocketException e) {
409 throw e;
410 }
411 }
412 }
413 }
414 endpoint = mapOrFail(endpoint, supportedAddressClass);
415 }
416
417 Objects.requireNonNull(endpoint);
418
419 if (!supportedAddressClass.isAssignableFrom(endpoint.getClass())) {
420 throw new IllegalArgumentException("Can only connect to endpoints of type "
421 + supportedAddressClass.getName() + ", got: " + endpoint.getClass() + ": " + endpoint);
422 }
423
424 return (AFSocketAddress) endpoint;
425 }
426
427
428
429
430
431
432 protected final byte[] getBytes() {
433 return bytes;
434 }
435
436
437
438
439
440
441
442
443
444
445
446
447 public final InetAddress wrapAddress() {
448 return AFInetAddress.wrapAddress(bytes, getAddressFamily());
449 }
450
451
452
453
454
455
456
457 @FunctionalInterface
458 protected interface AFSocketAddressConstructor<T extends AFSocketAddress> {
459
460
461
462
463
464
465
466
467
468 @NonNull
469 T newAFSocketAddress(int port, byte[] socketAddress, Lease<ByteBuffer> nativeAddress)
470 throws SocketException;
471 }
472
473
474
475
476
477
478
479
480
481
482
483
484 @SuppressWarnings({"unchecked", "null"})
485 protected static final <A extends AFSocketAddress> A resolveAddress(final byte[] socketAddress,
486 int port, AFAddressFamily<A> af) throws SocketException {
487 if (socketAddress.length == 0) {
488 throw new SocketException("Address cannot be empty");
489 }
490
491 if (port == -1) {
492 port = 0;
493 }
494
495 try (Lease<ByteBuffer> lease = SOCKETADDRESS_BUFFER_TL.take()) {
496 ByteBuffer direct = lease.get();
497 int limit = NativeUnixSocket.isLoaded() ? NativeUnixSocket.bytesToSockAddr(af.getDomain(),
498 direct, socketAddress) : -1;
499 if (limit == -1) {
500
501 return af.getAddressConstructor().newAFSocketAddress(port, socketAddress, null);
502 } else if (limit > SOCKADDR_MAX_LEN) {
503 throw new IllegalStateException("Unexpected address length");
504 }
505 direct.rewind();
506 direct.limit(limit);
507
508 A instance;
509 synchronized (AFSocketAddress.class) {
510 Map<ByteBuffer, AFSocketAddress> map;
511 Map<Integer, Map<ByteBuffer, AFSocketAddress>> mapPorts = ADDRESS_CACHE.get(af);
512 if (mapPorts == null) {
513 instance = null;
514 mapPorts = new HashMap<>();
515 map = new HashMap<>();
516 mapPorts.put(port, map);
517 ADDRESS_CACHE.put(af, mapPorts);
518 } else {
519 map = mapPorts.get(port);
520 if (map == null) {
521 instance = null;
522 map = new HashMap<>();
523 mapPorts.put(port, map);
524 } else {
525 instance = (A) map.get(direct);
526 }
527 }
528
529 if (instance == null) {
530 ByteBuffer key = newSockAddrKeyBuffer(limit);
531 key.put(direct);
532 key = key.asReadOnlyBuffer();
533
534 instance = af.getAddressConstructor().newAFSocketAddress(port, socketAddress, ObjectPool
535 .unpooledLease(key));
536
537 map.put(key, instance);
538 }
539 }
540 return instance;
541 }
542 }
543
544 @SuppressWarnings("null")
545 static final <A extends AFSocketAddress> A ofInternal(ByteBuffer socketAddressBuffer,
546 AFAddressFamily<A> af) throws SocketException {
547 synchronized (AFSocketAddress.class) {
548 socketAddressBuffer.rewind();
549
550 Map<Integer, Map<ByteBuffer, AFSocketAddress>> mapPorts = ADDRESS_CACHE.get(af);
551 if (mapPorts != null) {
552 Map<ByteBuffer, AFSocketAddress> map = mapPorts.get(0);
553
554 if (map != null) {
555 @SuppressWarnings("unchecked")
556 A address = (A) map.get(socketAddressBuffer);
557 if (address != null) {
558 return address;
559 }
560 }
561 }
562
563 try (Lease<ByteBuffer> leasedBuffer = socketAddressBuffer.isDirect() ? null
564 : getNativeAddressDirectBuffer(Math.min(socketAddressBuffer.limit(), SOCKADDR_MAX_LEN))) {
565 if (leasedBuffer != null) {
566 ByteBuffer buf = leasedBuffer.get();
567 buf.put(socketAddressBuffer);
568 socketAddressBuffer = buf;
569 }
570
571 byte[] sockAddrToBytes = NativeUnixSocket.sockAddrToBytes(af.getDomain(),
572 socketAddressBuffer);
573 if (sockAddrToBytes == null) {
574 return null;
575 } else {
576 return AFSocketAddress.resolveAddress(sockAddrToBytes, 0, af);
577 }
578 }
579 }
580 }
581
582
583
584
585
586
587
588 protected final synchronized InetAddress getInetAddress(AFAddressFamily<?> af) {
589 if (inetAddress == null) {
590 inetAddress = AFInetAddress.wrapAddress(bytes, af);
591 }
592 return inetAddress;
593 }
594
595
596
597
598
599
600 protected final InetAddress getInetAddress() {
601 return getInetAddress(getAddressFamily());
602 }
603
604 @SuppressWarnings("null")
605 static final @NonNull ByteBuffer newSockAddrDirectBuffer(int length) {
606 return ByteBuffer.allocateDirect(length);
607 }
608
609 @SuppressWarnings("null")
610 static final @NonNull ByteBuffer newSockAddrKeyBuffer(int length) {
611 return ByteBuffer.allocate(length);
612 }
613
614
615
616
617
618
619
620
621
622
623
624
625
626 @SuppressWarnings("null")
627 @NonNull
628 protected static final <A extends AFSocketAddress> A unwrap(InetAddress address, int port,
629 AFAddressFamily<A> af) throws SocketException {
630 Objects.requireNonNull(address);
631 return resolveAddress(AFInetAddress.unwrapAddress(address, af), port, af);
632 }
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647 @SuppressWarnings("null")
648 @NonNull
649 protected static final <A extends AFSocketAddress> A unwrap(String hostname, int port,
650 AFAddressFamily<A> af) throws SocketException {
651 Objects.requireNonNull(hostname);
652 return resolveAddress(AFInetAddress.unwrapAddress(hostname, af), port, af);
653 }
654
655 static final int unwrapAddressDirectBufferInternal(ByteBuffer socketAddressBuffer,
656 SocketAddress address) throws SocketException {
657 if (!NativeUnixSocket.isLoaded()) {
658 throw new SocketException("Unsupported operation; junixsocket native library is not loaded");
659 }
660 Objects.requireNonNull(address);
661
662 address = AFSocketAddress.mapOrFail(address, AFSocketAddress.class);
663 AFSocketAddress socketAddress = (AFSocketAddress) address;
664
665 byte[] addr = socketAddress.getBytes();
666 int domain = socketAddress.getAddressFamily().getDomain();
667
668 int len = NativeUnixSocket.bytesToSockAddr(domain, socketAddressBuffer, addr);
669 if (len == -1) {
670 throw new SocketException("Unsupported domain");
671 }
672 return len;
673 }
674
675
676
677
678
679
680
681 final Lease<ByteBuffer> getNativeAddressDirectBuffer() throws SocketException {
682 ByteBuffer address = nativeAddress;
683 if (address == null) {
684 throw (SocketException) new SocketException("Cannot access native address").initCause(
685 NativeUnixSocket.unsupportedException());
686 }
687 address = address.duplicate();
688
689 Lease<ByteBuffer> lease = getNativeAddressDirectBuffer(address.limit());
690 ByteBuffer direct = lease.get();
691 address.position(0);
692 direct.put(address);
693
694 return lease;
695 }
696
697 static final Lease<ByteBuffer> getNativeAddressDirectBuffer(int limit) {
698 Lease<ByteBuffer> lease = SOCKETADDRESS_BUFFER_TL.take();
699 ByteBuffer direct = lease.get();
700 direct.position(0);
701 direct.limit(limit);
702 return lease;
703 }
704
705
706
707
708
709
710
711
712 protected static final boolean isSupportedAddress(InetAddress addr, AFAddressFamily<?> af) {
713 return AFInetAddress.isSupportedAddress(addr, af);
714 }
715
716
717
718
719
720
721
722
723
724 public final void writeNativeAddressTo(ByteBuffer buf) throws IOException {
725 if (nativeAddress == null) {
726 throw (SocketException) new SocketException("Cannot access native address").initCause(
727 NativeUnixSocket.unsupportedException());
728 }
729 buf.put(nativeAddress);
730 }
731
732
733
734
735
736
737
738 public AFSocket<?> newConnectedSocket() throws IOException {
739 AFSocket<?> socket = getAddressFamily().newSocket();
740 socket.connect(this);
741 return socket;
742 }
743
744
745
746
747
748
749
750 public AFServerSocket<?> newBoundServerSocket() throws IOException {
751 AFServerSocket<?> serverSocket = getAddressFamily().newServerSocket();
752 serverSocket.bind(this);
753 return serverSocket;
754 }
755
756
757
758
759
760
761
762
763
764 public AFServerSocket<?> newForceBoundServerSocket() throws IOException {
765 AFServerSocket<?> serverSocket = getAddressFamily().newServerSocket();
766 serverSocket.forceBindAddress(this).bind(this);
767 return serverSocket;
768 }
769
770
771
772
773
774
775
776
777
778
779
780
781 @SuppressWarnings("PMD.ShortMethodName")
782 public static AFSocketAddress of(URI u) throws SocketException {
783 return of(u, -1);
784 }
785
786
787
788
789
790
791
792
793
794
795
796
797
798 @SuppressWarnings("PMD.ShortMethodName")
799 public static AFSocketAddress of(URI u, int overridePort) throws SocketException {
800 AFAddressFamily<?> af = AFAddressFamily.getAddressFamily(u);
801 if (af == null) {
802 throw new SocketException("Cannot resolve AFSocketAddress from URI scheme: " + u.getScheme());
803 }
804 return af.parseURI(u, overridePort);
805 }
806
807
808
809
810
811
812
813
814
815
816 public URI toURI(String scheme, URI template) throws IOException {
817 throw new IOException("Unsupported operation");
818 }
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834 public @Nullable @SuppressWarnings("PMD.NPathComplexity") String toSocatAddressString(
835 AFSocketType socketType, AFSocketProtocol socketProtocol) throws IOException {
836
837 if (SOCKADDR_NATIVE_FAMILY_OFFSET == -1 || SOCKADDR_NATIVE_DATA_OFFSET == -1) {
838 return null;
839 }
840 if (nativeAddress == null) {
841 throw (SocketException) new SocketException("Cannot access native address").initCause(
842 NativeUnixSocket.unsupportedException());
843 }
844 if (socketProtocol != null && socketProtocol.getId() != 0) {
845 throw new IOException("Protocol not (yet) supported");
846 }
847
848 int family = (nativeAddress.get(SOCKADDR_NATIVE_FAMILY_OFFSET) & 0xFF);
849 int type = socketType == null ? -1 : NativeUnixSocket.sockTypeToNative(socketType.getId());
850 StringBuilder sb = new StringBuilder();
851 sb.append(family);
852 if (type != -1) {
853 sb.append(':');
854 sb.append(type);
855 }
856 if (socketProtocol != null) {
857 sb.append(':');
858 sb.append(socketProtocol.getId());
859 }
860 sb.append(":x");
861 int n = nativeAddress.limit();
862 while (n > 1 && nativeAddress.get(n - 1) == 0) {
863 n--;
864 }
865 for (int pos = SOCKADDR_NATIVE_DATA_OFFSET; pos < n; pos++) {
866 byte b = nativeAddress.get(pos);
867 sb.append(String.format(Locale.ENGLISH, "%02x", b));
868 }
869 return sb.toString();
870 }
871
872
873
874
875
876
877
878
879
880
881
882
883
884 public boolean covers(AFSocketAddress other) {
885 return this.equals(other);
886 }
887
888
889
890
891
892
893
894
895 @SuppressFBWarnings("MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT")
896 private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
897 in.defaultReadObject();
898
899 String af = in.readUTF();
900 if ("undefined".equals(af)) {
901 this.addressFamily = null;
902 } else {
903 this.addressFamily = Objects.requireNonNull(AFAddressFamily.getAddressFamily(af),
904 "address family");
905 }
906 }
907
908
909
910
911
912
913
914 private void writeObject(ObjectOutputStream out) throws IOException {
915 out.defaultWriteObject();
916 out.writeUTF(addressFamily == null ? "undefined" : addressFamily.getJuxString());
917 }
918
919
920
921
922
923
924
925
926
927 static String toUnsignedString(int i) {
928 return Long.toString(toUnsignedLong(i));
929 }
930
931
932
933
934
935
936
937
938
939 static String toUnsignedString(int i, int radix) {
940 return Long.toUnsignedString(toUnsignedLong(i), radix);
941 }
942
943 private static long toUnsignedLong(long x) {
944 return x & 0xffffffffL;
945 }
946
947
948
949
950
951
952
953
954
955
956
957 protected static int parseUnsignedInt(String s, int radix) throws NumberFormatException {
958 if (s == null || s.isEmpty()) {
959 throw new NumberFormatException("Cannot parse null or empty string");
960 }
961
962 int len = s.length();
963 if (s.startsWith("-")) {
964 throw new NumberFormatException("Illegal leading minus sign on unsigned string " + s);
965 }
966
967 if (len <= 5 || (radix == 10 && len <= 9)) {
968 return Integer.parseInt(s, radix);
969 } else {
970 long ell = Long.parseLong(s, radix);
971 if ((ell & 0xffff_ffff_0000_0000L) == 0) {
972 return (int) ell;
973 } else {
974 throw new NumberFormatException("String value exceeds " + "range of unsigned int: " + s);
975 }
976 }
977 }
978
979
980
981
982
983
984
985
986
987 public static boolean canMap(SocketAddress addr) {
988 return canMap(addr, AFSocketAddress.class);
989 }
990
991
992
993
994
995
996
997
998
999
1000
1001 public static boolean canMap(SocketAddress addr,
1002 Class<? extends AFSocketAddress> targetAddressClass) {
1003 if (addr == null) {
1004 return true;
1005 } else if (targetAddressClass.isAssignableFrom(addr.getClass())) {
1006 return true;
1007 }
1008 AFSupplier<? extends AFSocketAddress> supplier = SocketAddressUtil.supplyAFSocketAddress(addr);
1009 if (supplier == null) {
1010 return false;
1011 }
1012 AFSocketAddress afAddr = supplier.get();
1013 if (afAddr == null) {
1014 return false;
1015 }
1016 return (targetAddressClass.isAssignableFrom(afAddr.getClass()));
1017 }
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 public static AFSocketAddress mapOrFail(SocketAddress addr) {
1028 return mapOrFail(addr, AFSocketAddress.class);
1029 }
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041 @SuppressWarnings("null")
1042 public static <A extends AFSocketAddress> A mapOrFail(SocketAddress addr,
1043 Class<A> targetAddressClass) {
1044 if (addr == null) {
1045 return null;
1046 } else if (targetAddressClass.isAssignableFrom(addr.getClass())) {
1047 return targetAddressClass.cast(addr);
1048 }
1049
1050 AFSupplier<? extends AFSocketAddress> supplier = SocketAddressUtil.supplyAFSocketAddress(addr);
1051 if (supplier == null) {
1052 throw new IllegalArgumentException("Can only bind to endpoints of type "
1053 + AFSocketAddress.class.getName() + ": " + addr);
1054 }
1055 AFSocketAddress afAddr = supplier.get();
1056 if (afAddr == null || !targetAddressClass.isAssignableFrom(afAddr.getClass())) {
1057 throw new IllegalArgumentException("Can only bind to endpoints of type "
1058 + AFSocketAddress.class.getName() + ", and this specific address is unsupported: "
1059 + addr);
1060 }
1061 return targetAddressClass.cast(afAddr);
1062 }
1063 }