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

net.dankito.utils.network.NetworkHelper.kt Maven / Gradle / Ivy

The newest version!
package net.dankito.utils.network

import org.slf4j.LoggerFactory
import java.io.IOException
import java.net.*
import java.util.*
import kotlin.collections.ArrayList


open class NetworkHelper : INetworkHelper {

    companion object {

        const val MaxPortNumber = 65535

        const val MinTcpPortNumber = 1

        const val MinUdpPortNumber = 0


        private val log = LoggerFactory.getLogger(NetworkHelper::class.java)
    }


    // in IPv6 there's no such thing as broadcast
    override fun getBroadcastAddress(networkInterface: NetworkInterface): Inet4Address? {
        for(address in networkInterface.inetAddresses) {
            if(address is Inet4Address) {
                try {
                    return getBroadcastAddress(address)
                } catch(e: Exception) { log.error("Could not determine Broadcast Address of " + address.hostAddress, e)}
            }
        }

        return null
    }

    override fun getBroadcastAddress(address: Inet4Address): Inet4Address? {
        val broadcastAddress = address.address
        broadcastAddress[broadcastAddress.size - 1] = 255.toByte()

        return Inet4Address.getByAddress(broadcastAddress) as? Inet4Address
    }

    /**
     * Returns MAC address of the given interface name.
     * @param interfaceName eth0, wlan0 or NULL=use first interface
     * *
     * @return  mac address or empty string
     */
    override fun getMACAddress(interfaceName: String?): String {
        try {
            val interfaces = Collections.list(NetworkInterface.getNetworkInterfaces())
            for (intf in interfaces) {
                if (interfaceName != null) {
                    if (!intf.name.equals(interfaceName, ignoreCase = true)) continue
                }
                val mac = intf.hardwareAddress ?: return ""
                val buf = StringBuilder()
                for (idx in mac.indices)
                    buf.append(String.format("%02X:", mac[idx]))
                if (buf.length > 0) buf.deleteCharAt(buf.length - 1)
                return buf.toString()
            }
        } catch (ex: Exception) {
        }
        // for now eat exceptions
        return ""
    }

    /**
     * Get IP address from first non-localhost interface
     * @param useIPv4  true=return ipv4, false=return ipv6
     * *
     * @return  address or empty string
     */
    override fun getIPAddress(useIPv4: Boolean): InetAddress? {
        val addresses = getIPAddresses(useIPv4)
        if (addresses.size > 0) {
            return addresses[0]
        }

        return null
    }

    override fun getIPAddresses(onlyIPv4: Boolean): List {
        val addresses = ArrayList()

        try {
            for(networkInterface in getConnectedRealNetworkInterfaces()) {
                addresses.addAll(getIPAddresses(networkInterface, onlyIPv4))
            }
        } catch (ignored: Exception) { } // for now eat exceptions

        return addresses
    }

    override fun getIPAddresses(networkInterface: NetworkInterface, onlyIPv4: Boolean): List {
        val addresses = ArrayList()
        val interfaceAddresses = Collections.list(networkInterface.inetAddresses)

        for(address in interfaceAddresses) {
            if(address.isLoopbackAddress == false) {
                if(onlyIPv4 == false || address is Inet4Address) {
                    addresses.add(address)
                }
            }
        }

        return addresses
    }

    override fun getRealNetworkInterfaces(): Collection {
        val allInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces())

        return allInterfaces.filter { shouldInterfaceBeIgnored(it) == false }
    }

    override fun getConnectedRealNetworkInterfaces(): Collection {
        return getRealNetworkInterfaces().filter { it.isUp }
    }

    @Throws(SocketException::class)
    protected open fun shouldInterfaceBeIgnored(networkInterface: NetworkInterface): Boolean {
        return networkInterface.isLoopback ||
                isCellularOrUsbInterface(networkInterface) ||
                isDockerInterface(networkInterface) ||
                isDummyInterface(networkInterface)
    }

    protected open fun isCellularOrUsbInterface(networkInterface: NetworkInterface): Boolean {
        return networkInterface.name.startsWith("rmnet") // see for example https://stackoverflow.com/a/33748594
    }

    protected open fun isDockerInterface(networkInterface: NetworkInterface): Boolean {
        return networkInterface.name.startsWith("docker")
    }

    protected open fun isDummyInterface(networkInterface: NetworkInterface): Boolean {
        return networkInterface.name.startsWith("dummy")
    }


    override fun isSocketCloseException(exception: Exception): Boolean {
        return exception is SocketException && "Socket closed" == exception.message
    }


    override fun isTcpPortAvailable(port: Int): Boolean {
        if (port < MinTcpPortNumber || port > MaxPortNumber) {
            throw IllegalArgumentException("Port has to be in range [$MinTcpPortNumber, $MaxPortNumber]")
        }

        var serverSocket: ServerSocket? = null

        try {
            serverSocket = ServerSocket(port)
            serverSocket.reuseAddress = true

            return true
        }
        catch (e: IOException) { }
        finally {
            try {
                serverSocket?.close()
            } catch (ignored: Exception) { }
        }

        return false
    }

    override fun isUdpPortAvailable(port: Int): Boolean {
        if (port < MinUdpPortNumber || port > MaxPortNumber) {
            throw IllegalArgumentException("Port has to be in range [$MinUdpPortNumber, $MaxPortNumber]")
        }

        var datagramSocket: DatagramSocket? = null
        try {
            datagramSocket = DatagramSocket(port)
            datagramSocket.reuseAddress = true

            return true
        } catch (e: IOException) {
        } finally {
            try {
                datagramSocket?.close()
            } catch (ignored: Exception) { }
        }

        return false
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy