Критический фикс отправки после верификации устройства
Some checks failed
Android Kernel Build / build (push) Has been cancelled

This commit is contained in:
2026-04-16 23:02:18 +05:00
parent 2fc652cacb
commit 103ae134a5

View File

@@ -311,14 +311,35 @@ class Protocol(
when (resolve.solution) {
DeviceResolveSolution.ACCEPT -> {
log("✅ DEVICE VERIFICATION ACCEPTED (deviceId=${shortKey(resolve.deviceId, 12)})")
if (_state.value == ProtocolState.DEVICE_VERIFICATION_REQUIRED) {
val stateAtAccept = _state.value
if (stateAtAccept == ProtocolState.AUTHENTICATED) {
log("✅ ACCEPT ignored: already authenticated")
return@waitPacket
}
if (stateAtAccept == ProtocolState.DEVICE_VERIFICATION_REQUIRED) {
setState(ProtocolState.CONNECTED, "Device verification accepted")
val publicKey = lastPublicKey
val privateHash = lastPrivateHash
if (!publicKey.isNullOrBlank() && !privateHash.isNullOrBlank()) {
}
val publicKey = lastPublicKey
val privateHash = lastPrivateHash
if (publicKey.isNullOrBlank() || privateHash.isNullOrBlank()) {
log("⚠️ ACCEPT received but credentials are missing, waiting for reconnect")
return@waitPacket
}
when (_state.value) {
ProtocolState.DISCONNECTED -> {
log("🔄 ACCEPT while disconnected -> reconnecting")
connect()
}
ProtocolState.CONNECTING -> {
log("⏳ ACCEPT while connecting -> waiting for onOpen auto-handshake")
}
else -> {
startHandshake(publicKey, privateHash, lastDevice)
} else {
log("⚠️ ACCEPT received but credentials are missing, waiting for reconnect")
}
}
}
@@ -644,7 +665,14 @@ class Protocol(
val currentState = _state.value
val socket = webSocket
val socketReady = socket != null
val authReady = handshakeComplete && currentState == ProtocolState.AUTHENTICATED
val authReady = currentState == ProtocolState.AUTHENTICATED
if (authReady && !handshakeComplete) {
// Defensive self-heal:
// AUTHENTICATED state must imply completed handshake.
// If these flags diverge, message sending can be stuck in queue forever.
log("⚠️ AUTHENTICATED with handshakeComplete=false -> self-heal handshakeComplete=true")
handshakeComplete = true
}
val preAuthAllowedPacket =
packet is PacketSignalPeer || packet is PacketWebRTC || packet is PacketIceServers
val preAuthReady =
@@ -772,6 +800,13 @@ class Protocol(
private fun handleDisconnect() {
val previousState = _state.value
log("🔌 DISCONNECT HANDLER: previousState=$previousState, manuallyClosed=$isManuallyClosed, reconnectAttempts=$reconnectAttempts, isConnecting=$isConnecting")
// Duplicate callbacks are possible (e.g. heartbeat failure + onFailure/onClosed).
// If we are already disconnected and a reconnect is pending, avoid scheduling another one.
if (previousState == ProtocolState.DISCONNECTED && reconnectJob?.isActive == true) {
log("⚠️ DISCONNECT DUPLICATE: reconnect already scheduled, skipping")
return
}
// КРИТИЧНО: если уже идет подключение, не делаем ничего
if (isConnecting) {
@@ -799,12 +834,16 @@ class Protocol(
// КРИТИЧНО: отменяем предыдущий reconnect job если есть
reconnectJob?.cancel()
// Экспоненциальная задержка: 1s, 2s, 4s, 8s, максимум 30s
val delayMs = minOf(1000L * (1 shl minOf(reconnectAttempts - 1, 4)), 30000L)
log("🔄 SCHEDULING RECONNECT: attempt #$reconnectAttempts, delay=${delayMs}ms")
// Экспоненциальная задержка: 1s, 2s, 4s, 8s, 16s, максимум 30s.
// IMPORTANT: reconnectAttempts may be 0 right after AUTHENTICATED reset.
// Using (1 shl -1) causes overflow (seen in logs as -2147483648000ms).
val nextAttemptNumber = (reconnectAttempts + 1).coerceAtLeast(1)
val exponent = (nextAttemptNumber - 1).coerceIn(0, 4)
val delayMs = minOf(1000L * (1L shl exponent), 30000L)
log("🔄 SCHEDULING RECONNECT: attempt #$nextAttemptNumber, delay=${delayMs}ms")
if (reconnectAttempts > 20) {
log("⚠️ WARNING: Too many reconnect attempts ($reconnectAttempts), may be stuck in loop")
if (nextAttemptNumber > 20) {
log("⚠️ WARNING: Too many reconnect attempts ($nextAttemptNumber), may be stuck in loop")
}
reconnectJob = scope.launch {