diff --git a/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt b/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt index b08ca3e..080f1df 100644 --- a/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt +++ b/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt @@ -85,6 +85,15 @@ class ReflectorClient( @Volatile private var fatal = false + /** + * Была ли хотя бы одна успешная сессия за текущее подключение. + * Если да — креды уже проверены, поэтому ошибки на рукопожатии считаем + * временными (сервер мог ещё держать старую сессию после обрыва) и + * продолжаем автопереподключение вместо показа «ошибки авторизации». + */ + @Volatile + private var everReady = false + @Volatile private var tcpSocket: Socket? = null private var udpSocket: DatagramSocket? = null @@ -107,6 +116,7 @@ class ReflectorClient( this.settings = settings manualDisconnect.set(false) fatal = false + everReady = false if (running.get()) { // Перезапуск с новыми настройками (например, смена профиля) running.set(false) @@ -399,6 +409,7 @@ class ReflectorClient( serverCodecs = info.codecs callbacks.onServerInfo(info) state = STATE_READY + everReady = true callbacks.onState(STATE_READY) // Сначала сообщаем о себе (версия ПО для дашборда), затем // выбираем TG для передачи и подписываемся на прослушивание @@ -441,9 +452,17 @@ class ReflectorClient( ReflectorProtocol.MSG_ERROR -> { val err = MsgParser.errorMessage(msg.fields) - Log.w(TAG, "MSG_ERROR: $err") + Log.w(TAG, "MSG_ERROR: $err (state=$state, everReady=$everReady)") if (state < STATE_READY) { - stopFatal(err.ifEmpty { "Access denied" }) + if (everReady) { + // Креды проверены ранее: ошибка на рукопожатии почти + // всегда временная (сервер ещё держит старую сессию + // после короткого обрыва) — переподключаемся заново. + callbacks.onState(STATE_ERROR, err.ifEmpty { "Переподключение" }) + abortSockets() + } else { + stopFatal(err.ifEmpty { "Access denied" }) + } return false } callbacks.onError(err) @@ -452,7 +471,13 @@ class ReflectorClient( else -> Unit // неизвестные сообщения игнорируются } } catch (e: Exception) { - stopFatal("Ошибка протокола: ${e.message}") + if (everReady) { + // Сбой после успешного подключения — не фатально, переподключаемся. + callbacks.onState(STATE_ERROR, "Ошибка протокола: ${e.message}") + abortSockets() + } else { + stopFatal("Ошибка протокола: ${e.message}") + } return false } return true @@ -478,7 +503,12 @@ class ReflectorClient( } private fun protocolError(detail: String): Boolean { - stopFatal(detail) + if (everReady) { + callbacks.onState(STATE_ERROR, detail) + abortSockets() + } else { + stopFatal(detail) + } return false }