reconnect: не уходить в «ошибку авторизации» при коротком обрыве
После короткого обрыва сервер ещё держит старую сессию и на рукопожатии присылает MSG_ERROR. Клиент трактовал любую ошибку до STATE_READY как фатальную (stopFatal → STATE_AUTH_FAILED) и прекращал переподключения. Теперь ошибки рукопожатия (MSG_ERROR, протокольные сбои, слишком большой кадр) считаются временными, если успешная сессия уже была (everReady): показываем STATE_ERROR и продолжаем автопереподключение. Фатально — только до первой успешной авторизации (реально неверные креды).
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user