View Javadoc
1   /*
2    * junixsocket
3    *
4    * Copyright 2009-2026 Christian Kohlschütter
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.newsclub.net.unix;
19  
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import java.net.InetAddress;
23  import java.net.SocketAddress;
24  import java.net.SocketException;
25  import java.net.URI;
26  import java.nio.ByteBuffer;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.Objects;
30  import java.util.Set;
31  
32  import org.newsclub.net.unix.pool.ObjectPool.Lease;
33  
34  /**
35   * An {@link AFSocketAddress} for unknown socket types.
36   *
37   * @author Christian Kohlschütter
38   */
39  public final class AFGenericSocketAddress extends AFSocketAddress {
40    private static final long serialVersionUID = 1L; // do not change!
41  
42    private static AFAddressFamily<AFGenericSocketAddress> family;
43    private static final String SELECTOR_PROVIDER_CLASS =
44        "org.newsclub.net.unix.generic.AFGenericSelectorProvider";
45  
46    private AFGenericSocketAddress(int port, final byte[] socketAddress,
47        Lease<ByteBuffer> nativeAddress) throws SocketException {
48      super(port, socketAddress, nativeAddress, addressFamily());
49    }
50  
51    private static AFGenericSocketAddress newAFSocketAddress(int port, final byte[] socketAddress,
52        Lease<ByteBuffer> nativeAddress) throws SocketException {
53      return newDeserializedAFSocketAddress(port, socketAddress, nativeAddress, addressFamily(),
54          AFGenericSocketAddress::new);
55    }
56  
57    /**
58     * Returns an {@link AFGenericSocketAddress} given a special {@link InetAddress} that encodes the
59     * byte sequence of an unknown-type socket address, like those returned by {@link #wrapAddress()}.
60     *
61     * @param address The "special" {@link InetAddress}.
62     * @param port The port (use 0 for "none").
63     * @return The {@link AFGenericSocketAddress} instance.
64     * @throws SocketException if the operation fails, for example when an unsupported address is
65     *           specified.
66     */
67    public static AFGenericSocketAddress unwrap(InetAddress address, int port)
68        throws SocketException {
69      return AFSocketAddress.unwrap(address, port, addressFamily());
70    }
71  
72    /**
73     * Returns an {@link AFGenericSocketAddress} given a special {@link InetAddress} hostname that
74     * encodes the byte sequence of an unknown-type socket address, like those returned by
75     * {@link #wrapAddress()}.
76     *
77     * @param hostname The "special" hostname, as provided by {@link InetAddress#getHostName()}.
78     * @param port The port (use 0 for "none").
79     * @return The {@link AFGenericSocketAddress} instance.
80     * @throws SocketException if the operation fails, for example when an unsupported address is
81     *           specified.
82     */
83    public static AFGenericSocketAddress unwrap(String hostname, int port) throws SocketException {
84      return AFSocketAddress.unwrap(hostname, port, addressFamily());
85    }
86  
87    /**
88     * Returns an {@link AFGenericSocketAddress} given a generic {@link SocketAddress}.
89     *
90     * @param address The address to unwrap.
91     * @return The {@link AFGenericSocketAddress} instance.
92     * @throws SocketException if the operation fails, for example when an unsupported address is
93     *           specified.
94     */
95    public static AFGenericSocketAddress unwrap(SocketAddress address) throws SocketException {
96      Objects.requireNonNull(address);
97      if (!isSupportedAddress(address)) {
98        throw new SocketException("Unsupported address");
99      }
100     return (AFGenericSocketAddress) address;
101   }
102 
103   @Override
104   public String toString() {
105     int port = getPort();
106 
107     return getClass().getName() + "[" + (port == 0 ? "" : "port=" + port + ";") + "bytes=" + Arrays
108         .toString(getBytes()) + "]";
109   }
110 
111   /**
112    * Returns the native representation of this generic address, which is most likely not portable.
113    * <p>
114    * The address contains the sa_family identifier as the first byte, and, on some platforms only,
115    * the address length, as the second byte.
116    *
117    * @return A new byte array containing the system-specific representation of that address.
118    */
119   public byte[] toBytes() {
120     byte[] bytes = getBytes();
121     return Arrays.copyOf(bytes, bytes.length);
122   }
123 
124   @Override
125   public boolean hasFilename() {
126     return false;
127   }
128 
129   @Override
130   public File getFile() throws FileNotFoundException {
131     throw new FileNotFoundException("no file");
132   }
133 
134   /**
135    * Checks if an {@link InetAddress} can be unwrapped to an {@link AFGenericSocketAddress}.
136    *
137    * @param addr The instance to check.
138    * @return {@code true} if so.
139    * @see #wrapAddress()
140    * @see #unwrap(InetAddress, int)
141    */
142   public static boolean isSupportedAddress(InetAddress addr) {
143     return AFSocketAddress.isSupportedAddress(addr, addressFamily());
144   }
145 
146   /**
147    * Checks if a {@link SocketAddress} can be unwrapped to an {@link AFGenericSocketAddress}.
148    *
149    * @param addr The instance to check.
150    * @return {@code true} if so.
151    * @see #unwrap(InetAddress, int)
152    */
153   public static boolean isSupportedAddress(SocketAddress addr) {
154     return (addr instanceof AFGenericSocketAddress);
155   }
156 
157   /**
158    * Returns the corresponding {@link AFAddressFamily}.
159    *
160    * @return The address family instance.
161    */
162   @SuppressWarnings("null")
163   public static synchronized AFAddressFamily<AFGenericSocketAddress> addressFamily() {
164     if (family == null) {
165       family = AFAddressFamily.registerAddressFamily("generic", //
166           AFGenericSocketAddress.class, new AFSocketAddressConfig<AFGenericSocketAddress>() {
167 
168             private final AFSocketAddressConstructor<AFGenericSocketAddress> addrConstr =
169                 isUseDeserializationForInit() ? AFGenericSocketAddress::newAFSocketAddress
170                     : AFGenericSocketAddress::new;
171 
172             @Override
173             protected AFGenericSocketAddress parseURI(URI u, int port) throws SocketException {
174               return AFGenericSocketAddress.of(u, port);
175             }
176 
177             @Override
178             protected AFSocketAddressConstructor<AFGenericSocketAddress> addressConstructor() {
179               return addrConstr;
180             }
181 
182             @Override
183             protected String selectorProviderClassname() {
184               return SELECTOR_PROVIDER_CLASS;
185             }
186 
187             @Override
188             protected Set<String> uriSchemes() {
189               return Collections.emptySet();
190             }
191           });
192       try {
193         Class.forName(SELECTOR_PROVIDER_CLASS);
194       } catch (ClassNotFoundException e) {
195         // ignore
196       }
197     }
198     return family;
199   }
200 
201   /**
202    * Returns an {@link AFGenericSocketAddress} for the given URI, if possible.
203    *
204    * @param uri The URI.
205    * @return The address.
206    * @throws SocketException if the operation fails.
207    */
208   @SuppressWarnings("PMD.ShortMethodName")
209   public static AFGenericSocketAddress of(URI uri) throws SocketException {
210     return of(uri, -1);
211   }
212 
213   /**
214    * Returns an {@link AFGenericSocketAddress} for the given URI, if possible.
215    *
216    * @param uri The URI.
217    * @param overridePort The port to forcibly use, or {@code -1} for "don't override".
218    * @return The address.
219    * @throws SocketException if the operation fails.
220    */
221   @SuppressWarnings({"PMD.ShortMethodName"})
222   public static AFGenericSocketAddress of(URI uri, int overridePort) throws SocketException {
223     throw new SocketException("Unsupported");
224   }
225 }