All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jupnp.android.AndroidNetworkAddressFactory Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2011-2025 4th Line GmbH, Switzerland and others
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License Version 1 or later
 * ("CDDL") (collectively, the "License"). You may not use this file
 * except in compliance with the License. See LICENSE.txt for more
 * information.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * SPDX-License-Identifier: CDDL-1.0
 */
package org.jupnp.android;

import java.lang.reflect.Field;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;

import org.jupnp.transport.impl.NetworkAddressFactoryImpl;
import org.jupnp.transport.spi.InitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This factory tries to work around and patch some Android bugs.
 *
 * @author Michael Pujos
 * @author Christian Bauer
 */
public class AndroidNetworkAddressFactory extends NetworkAddressFactoryImpl {

    private final Logger logger = LoggerFactory.getLogger(AndroidNetworkAddressFactory.class);

    public AndroidNetworkAddressFactory(int streamListenPort, int multicastResponsePort) {
        super(streamListenPort, multicastResponsePort);
    }

    @Override
    protected boolean requiresNetworkInterface() {
        return false;
    }

    @Override
    protected boolean isUsableAddress(NetworkInterface networkInterface, InetAddress address) {
        boolean result = super.isUsableAddress(networkInterface, address);
        if (result) {
            // TODO: Workaround Android DNS reverse lookup issue, still a problem on ICS+?
            // http://4thline.org/projects/mailinglists.html#nabble-td3011461
            String hostName = address.getHostAddress();

            Field field0;
            Object target;

            try {

                try {
                    field0 = InetAddress.class.getDeclaredField("holder");
                    field0.setAccessible(true);
                    target = field0.get(address);
                    field0 = target.getClass().getDeclaredField("hostName");
                } catch (NoSuchFieldException e) {
                    // Let's try the non-OpenJDK variant
                    field0 = InetAddress.class.getDeclaredField("hostName");
                    target = address;
                }

                if (field0 != null && target != null && hostName != null) {
                    field0.setAccessible(true);
                    field0.set(target, hostName);
                } else {
                    return false;
                }

            } catch (Exception e) {
                logger.error("Failed injecting hostName to work around Android InetAddress DNS bug: {}", address, e);
                return false;
            }
        }
        return result;
    }

    @Override
    public InetAddress getLocalAddress(NetworkInterface networkInterface, boolean isIPv6, InetAddress remoteAddress) {
        // TODO: This is totally random because we can't access low level InterfaceAddress on Android!
        for (InetAddress localAddress : getInetAddresses(networkInterface)) {
            if (isIPv6 && localAddress instanceof Inet6Address) {
                return localAddress;
            }
            if (!isIPv6 && localAddress instanceof Inet4Address) {
                return localAddress;
            }
        }
        throw new IllegalStateException(
                "Can't find any IPv4 or IPv6 address on interface: " + networkInterface.getDisplayName());
    }

    @Override
    protected void discoverNetworkInterfaces() throws InitializationException {
        try {
            super.discoverNetworkInterfaces();
        } catch (Exception e) {
            // TODO: ICS bug on some models with network interface disappearing while enumerated
            // http://code.google.com/p/android/issues/detail?id=33661
            logger.warn("Exception while enumerating network interfaces, trying once more", e);
            super.discoverNetworkInterfaces();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy