Критический фикс отправки после верификации устройства
Some checks failed
Android Kernel Build / build (push) Has been cancelled
Some checks failed
Android Kernel Build / build (push) Has been cancelled
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user