Improvements to connection publishing for sync.

This commit is contained in:
Koen J 2025-06-05 10:31:13 +02:00
commit 4d170db5e0
3 changed files with 46 additions and 23 deletions

View file

@ -339,6 +339,33 @@ fun ByteArray.fromGzip(): ByteArray {
return outputStream.toByteArray()
}
fun findCandidateAddresses(): List<InetAddress> {
val candidates = NetworkInterface.getNetworkInterfaces()
.toList()
.asSequence()
.filter(::isUsableInterface)
.flatMap { nif ->
nif.interfaceAddresses
.asSequence()
.mapNotNull { ia ->
ia.address.takeIf(::isUsableAddress)?.let { addr ->
nif to ia
}
}
}
.toList()
return candidates
.sortedWith(
compareBy<Pair<NetworkInterface, InterfaceAddress>>(
{ addressScore(it.second.address) },
{ interfaceScore(it.first) },
{ -it.second.networkPrefixLength.toInt() },
{ -it.first.mtu }
)
).map { it.second.address }
}
fun findPreferredAddress(): InetAddress? {
val candidates = NetworkInterface.getNetworkInterfaces()
.toList()

View file

@ -328,7 +328,7 @@ class SyncService(
val now = System.currentTimeMillis()
synchronized(_mdnsCache) {
for ((pkey, info) in _mdnsCache) {
if (!database.isAuthorized(pkey) || isConnected(pkey)) continue
if (!database.isAuthorized(pkey) || getLinkType(pkey) == LinkType.Direct) continue
val last = synchronized(_lastConnectTimesMdns) {
_lastConnectTimesMdns[pkey] ?: 0L
@ -360,8 +360,8 @@ class SyncService(
while (_started) {
val authorizedDevices = database.getAllAuthorizedDevices() ?: arrayOf()
val addressesToConnect = authorizedDevices.mapNotNull {
val connected = isConnected(it)
if (connected) {
val connectedDirectly = getLinkType(it) == LinkType.Direct
if (connectedDirectly) {
return@mapNotNull null
}
@ -468,8 +468,13 @@ class SyncService(
while (_started && !socketClosed) {
val unconnectedAuthorizedDevices =
database.getAllAuthorizedDevices()
?.filter { !isConnected(it) }?.toTypedArray()
?: arrayOf()
?.filter {
if (Settings.instance.synchronization.connectLocalDirectThroughRelay) {
getLinkType(it) != LinkType.Direct
} else {
!isConnected(it)
}
}?.toTypedArray() ?: arrayOf()
relaySession.publishConnectionInformation(
unconnectedAuthorizedDevices,
settings.listenerPort,
@ -497,7 +502,7 @@ class SyncService(
val potentialLocalAddresses =
connectionInfo.ipv4Addresses
.filter { it != connectionInfo.remoteIp }
if (connectionInfo.allowLocalDirect && Settings.instance.synchronization.connectLocalDirectThroughRelay) {
if (getLinkType(targetKey) != LinkType.Direct && connectionInfo.allowLocalDirect && Settings.instance.synchronization.connectLocalDirectThroughRelay) {
Thread {
try {
Log.v(
@ -529,7 +534,7 @@ class SyncService(
// TODO: Implement hole punching if needed
}
if (connectionInfo.allowRemoteRelayed && Settings.instance.synchronization.connectThroughRelay) {
if (getLinkType(targetKey) == LinkType.None && connectionInfo.allowRemoteRelayed && Settings.instance.synchronization.connectThroughRelay) {
try {
Logger.v(
TAG,
@ -741,6 +746,7 @@ class SyncService(
)
}
fun getLinkType(publicKey: String): LinkType = synchronized(_sessions) { _sessions[publicKey]?.linkType ?: LinkType.None }
fun isConnected(publicKey: String): Boolean = synchronized(_sessions) { _sessions[publicKey]?.connected ?: false }
fun isAuthorized(publicKey: String): Boolean = database.isAuthorized(publicKey)
fun getSession(publicKey: String): SyncSession? = synchronized(_sessions) { _sessions[publicKey] }

View file

@ -2,6 +2,7 @@ package com.futo.platformplayer.sync.internal
import android.os.Build
import com.futo.platformplayer.ensureNotMainThread
import com.futo.platformplayer.findCandidateAddresses
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.noise.protocol.CipherStatePair
import com.futo.platformplayer.noise.protocol.DHState
@ -1078,20 +1079,9 @@ class SyncSocketSession {
) {
if (authorizedKeys.size > 255) throw IllegalArgumentException("Number of authorized keys exceeds 255")
val ipv4Addresses = mutableListOf<String>()
val ipv6Addresses = mutableListOf<String>()
for (nic in NetworkInterface.getNetworkInterfaces()) {
if (nic.isUp) {
for (addr in nic.inetAddresses) {
if (!addr.isLoopbackAddress) {
when (addr) {
is Inet4Address -> ipv4Addresses.add(addr.hostAddress)
is Inet6Address -> ipv6Addresses.add(addr.hostAddress)
}
}
}
}
}
val candidateAddresses = findCandidateAddresses()
val ipv4Addresses = candidateAddresses.filterIsInstance<Inet4Address>()
val ipv6Addresses = candidateAddresses.filterIsInstance<Inet6Address>()
val deviceName = getDeviceName()
val nameBytes = getLimitedUtf8Bytes(deviceName, 255)
@ -1103,12 +1093,12 @@ class SyncSocketSession {
data.put(nameBytes)
data.put(ipv4Addresses.size.toByte())
for (addr in ipv4Addresses) {
val addrBytes = InetAddress.getByName(addr).address
val addrBytes = addr.address
data.put(addrBytes)
}
data.put(ipv6Addresses.size.toByte())
for (addr in ipv6Addresses) {
val addrBytes = InetAddress.getByName(addr).address
val addrBytes = addr.address
data.put(addrBytes)
}
data.put(if (allowLocalDirect) 1 else 0)