host address retrieving through assigned subnet information and broadcast message to learn host address

This commit is contained in:
Constantin Leue
2026-08-03 23:10:11 +02:00
parent 4671b34f5b
commit 4e94102861
4 changed files with 87 additions and 16 deletions
@@ -19,6 +19,7 @@ import io.flutter.plugin.common.MethodChannel
import java.net.BindException
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.Inet4Address
import java.net.InetAddress
import java.net.InetSocketAddress
import java.util.concurrent.Executors
@@ -167,11 +168,18 @@ class MlrsNetworkPlugin(
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
currentNetwork = network
val gateway = gatewayAddressOf(connectivityManager.getLinkProperties(network))
val linkProperties = connectivityManager.getLinkProperties(network)
val gateway = gatewayAddressOf(linkProperties)
val broadcast = broadcastAddressOf(linkProperties)
val ssid = ssidOf(connectivityManager.getNetworkCapabilities(network))
if (ssid != null) reportedSsid = ssid
eventSink?.success(
mapOf("type" to "available", "gatewayAddress" to gateway, "ssid" to ssid),
mapOf(
"type" to "available",
"gatewayAddress" to gateway,
"broadcastAddress" to broadcast,
"ssid" to ssid,
),
)
}
@@ -225,6 +233,32 @@ class MlrsNetworkPlugin(
return route?.gateway?.hostAddress
}
/**
* Berechnet die Subnetz-Broadcast-Adresse (z.B. 192.168.4.255 fuer
* 192.168.4.42/24) aus der dem Geraet auf diesem Netz zugewiesenen
* IPv4-Adresse + Praefixlaenge. Dient als Bootstrap-Ziel fuer die erste
* MSP-Anfrage, wenn die tatsaechliche IP der mLRS-Bruecke (noch) nicht
* bekannt ist (Doku Kommunikationsschicht v2, Abschnitt 4/9:
* "Peer-Learning" versagt, wenn die Bruecke kein initiales Paket
* schickt und die geratene Standard-IP falsch liegt) - eine an die
* Broadcast-Adresse gesendete Anfrage erreicht die Bruecke unabhaengig
* von ihrer konkreten IP, ihre (unicast) Antwort verrät dann die echte
* Adresse.
*/
private fun broadcastAddressOf(linkProperties: LinkProperties?): String? {
val linkAddress = linkProperties?.linkAddresses
?.firstOrNull { it.address is Inet4Address } ?: return null
val ipBytes = linkAddress.address.address
val prefixLength = linkAddress.prefixLength
val broadcastBytes = ByteArray(4)
for (i in 0 until 4) {
val hostBitsInByte = (prefixLength - i * 8).coerceIn(0, 8)
val hostMaskByte = 0xFF shr hostBitsInByte
broadcastBytes[i] = (ipBytes[i].toInt() or hostMaskByte).toByte()
}
return InetAddress.getByAddress(broadcastBytes).hostAddress
}
/**
* Ermittelt die tatsaechliche SSID des verbundenen Netzes. Erfordert
* normalerweise ACCESS_FINE_LOCATION, ausser fuer die anfragende App
@@ -260,6 +294,10 @@ class MlrsNetworkPlugin(
// hier erkennbar mit BindException scheitert (Doku 3/9: "ist
// 14550 belegt, ausweichen, aber protokollieren").
newSocket.reuseAddress = false
// Ohne dies wirft send() an eine Broadcast-Adresse
// (broadcastAddressOf()) eine SocketException - noetig fuer
// den Bootstrap-Fallback in UdpTransport.connect().
newSocket.broadcast = true
var fallbackFromPort: Int? = null
try {
newSocket.bind(InetSocketAddress(requestedPort))