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

p-sim-ecu.doip-sim-ecu-dsl.0.15.1.source-code.NetworkManager.kt Maven / Gradle / Ivy

Go to download

This is a kotlin based domain specific language (dsl), to quickly and intuitively write custom DoIP ECU simulations.

The newest version!
import io.ktor.network.sockets.SocketAddress
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import library.DoipEntity
import library.DoipTcpConnectionMessageHandler
import library.DoipTcpSocket
import library.GroupDoipTcpConnectionMessageHandler
import library.TlsOptions
import org.slf4j.LoggerFactory
import java.net.Inet4Address
import java.net.InetAddress
import java.net.NetworkInterface

public open class NetworkManager(
    public val config: NetworkingData,
    public val doipEntities: List>,
) {
    private val log = LoggerFactory.getLogger(NetworkManager::class.java)
    private val udpNetworkBindings: MutableList = mutableListOf()
    private val tcpNetworkBindings: MutableList = mutableListOf()

    protected open fun findInterfaceByName(): NetworkInterface? {
        var foundInterface: NetworkInterface? = null
        NetworkInterface.getNetworkInterfaces()?.let { netIntf ->
            while (netIntf.hasMoreElements()) {
                val entry = netIntf.nextElement()
                if (entry.displayName != null && entry.displayName.equals(config.networkInterface, true)) {
                    foundInterface = entry
                    break
                }
                entry.subInterfaces?.let { subInterfaces ->
                    while (subInterfaces.hasMoreElements()) {
                        val subInterface = subInterfaces.nextElement()
                        if (subInterface.displayName != null && subInterface.displayName.equals(
                                config.networkInterface,
                                true
                            )
                        ) {
                            foundInterface = entry;
                            break
                        }
                    }
                }
                if (foundInterface != null) {
                    break
                }
            }
        }

        return foundInterface
    }

    protected open fun getAvailableIPAddresses(): Set {
        if (config.networkInterface.isNullOrBlank() || config.networkInterface == "0.0.0.0") {
            return setOf(InetAddress.getByName("0.0.0.0"))
        }
        val ipAddresses = mutableSetOf()
        findInterfaceByName()?.let { intf ->
            intf.inetAddresses?.let { inetAddresses ->
                while (inetAddresses.hasMoreElements()) {
                    val address = inetAddresses.nextElement()
                    if (address is Inet4Address) {
                        ipAddresses.add(address)
                    }
                    if (config.networkMode == NetworkMode.SINGLE_IP && ipAddresses.isNotEmpty()) {
                        break
                    }
                }
            }
        }
        if (ipAddresses.isEmpty()) {
            InetAddress.getByName(config.networkInterface)?.let { addr ->
                ipAddresses.add(addr)
            }
        }
        return ipAddresses
    }

    protected open fun buildStartupMap(): Map>> {
        val ipAddresses = getAvailableIPAddresses().toMutableList()
        if (ipAddresses.isEmpty()) {
            throw IllegalArgumentException("No network interface with the identifier ${config.networkInterface} could be found")
        }
        log.info("There are ${ipAddresses.size} ip address available, and we have ${doipEntities.size} doip entities")
        val entitiesByIP = mutableMapOf>>()
        doipEntities.forEach { entity ->
            val ip = if (ipAddresses.size == 1) {
                ipAddresses.first()
            } else {
                ipAddresses.removeFirst()
            }
            log.info("Assigning entity ${entity.name} to $ip")
            var entityList = entitiesByIP[ip.hostAddress]
            if (entityList == null) {
                entityList = mutableListOf()
                entitiesByIP[ip.hostAddress] = entityList
            }
            entityList.add(entity)
        }
        return entitiesByIP
    }

    public fun start() {
        val map = buildStartupMap()

        // UDP
        map.forEach { (address, entities) ->
            val unb = createUdpNetworkBinding(address, entities)
            unb.start()
            udpNetworkBindings.add(unb)
        }

        if (config.bindOnAnyForUdpAdditional && !map.containsKey("0.0.0.0")) {
            val unb = createUdpNetworkBindingAny()
            unb.start()
        }

        // TCP
        map.forEach { (address, entities) ->
            val tnb = createTcpNetworkBinding(address, entities)
            tnb.start()
            tcpNetworkBindings.add(tnb)
        }
    }

    protected open fun createTcpNetworkBinding(
        address: String,
        entities: List>
    ): TcpNetworkBinding =
        TcpNetworkBinding(this, address, config.localPort, config.tlsOptions, entities)

    protected open fun createUdpNetworkBinding(
        address: String,
        entities: List>
    ): UdpNetworkBinding =
        UdpNetworkBinding(address, config.localPort, config.broadcastEnable, config.broadcastAddress, entities)

    protected open fun createUdpNetworkBindingAny(): UdpNetworkBindingAny =
        UdpNetworkBindingAny(config.localPort, ::sendVirReply)

    protected open fun sendVirReply(socket: SocketAddress) {
        runBlocking(Dispatchers.IO) {
            runBlocking {
                udpNetworkBindings.forEach {
                    it.sendVirReply(socket)
                }
            }
        }
    }

    public open fun createTcpConnectionMessageHandler(doipEntities: List>, socket: DoipTcpSocket, tlsOptions: TlsOptions?): DoipTcpConnectionMessageHandler =
        GroupDoipTcpConnectionMessageHandler(doipEntities, socket, tlsOptions)

    public open suspend fun resendVams(entities: List>) {
        udpNetworkBindings.forEach {
            it.resendVams(entities)
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy