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