summaryrefslogtreecommitdiffhomepage
path: root/app/src/main/java/com/wireguard/config/InetAddresses.java
blob: 864082e21053a4372e25d00b19584db83ac9b4c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
 * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package com.wireguard.config;

import android.os.Build;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;

/**
 * Utility methods for creating instances of {@link InetAddress}.
 */
public final class InetAddresses {
    private static Method PARSER_METHOD;


    private static Method getParserMethod() {
        if (PARSER_METHOD != null)
                return PARSER_METHOD;
        try {
            // This method is only present on Android.
            // noinspection JavaReflectionMemberAccess
            PARSER_METHOD = InetAddress.class.getMethod("parseNumericAddress", String.class);
        } catch (final NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        return PARSER_METHOD;
    }

    private InetAddresses() {
        // Prevent instantiation.
    }

    /**
     * Parses a numeric IPv4 or IPv6 address without performing any DNS lookups.
     *
     * @param address a string representing the IP address
     * @return an instance of {@link Inet4Address} or {@link Inet6Address}, as appropriate
     */
    public static InetAddress parse(final String address) throws ParseException {
        if (address.isEmpty())
            throw new ParseException(InetAddress.class, address, "Empty address");
        try {
            if (Build.VERSION.SDK_INT < 29)
                return (InetAddress) getParserMethod().invoke(null, address);
            else
                return android.net.InetAddresses.parseNumericAddress(address);
        } catch (final IllegalAccessException | InvocationTargetException e) {
            final Throwable cause = e.getCause();
            // Re-throw parsing exceptions with the original type, as callers might try to catch
            // them. On the other hand, callers cannot be expected to handle reflection failures.
            if (cause instanceof IllegalArgumentException)
                throw new ParseException(InetAddress.class, address, cause);
            throw new RuntimeException(e);
        } catch (final IllegalArgumentException e) {
                throw new ParseException(InetAddress.class, address, e);
        }
    }
}