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
|
@Volatile
|
||||||
private var fatal = false
|
private var fatal = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Была ли хотя бы одна успешная сессия за текущее подключение.
|
||||||
|
* Если да — креды уже проверены, поэтому ошибки на рукопожатии считаем
|
||||||
|
* временными (сервер мог ещё держать старую сессию после обрыва) и
|
||||||
|
* продолжаем автопереподключение вместо показа «ошибки авторизации».
|
||||||
|
*/
|
||||||
|
@Volatile
|
||||||
|
private var everReady = false
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var tcpSocket: Socket? = null
|
private var tcpSocket: Socket? = null
|
||||||
private var udpSocket: DatagramSocket? = null
|
private var udpSocket: DatagramSocket? = null
|
||||||
@@ -107,6 +116,7 @@ class ReflectorClient(
|
|||||||
this.settings = settings
|
this.settings = settings
|
||||||
manualDisconnect.set(false)
|
manualDisconnect.set(false)
|
||||||
fatal = false
|
fatal = false
|
||||||
|
everReady = false
|
||||||
if (running.get()) {
|
if (running.get()) {
|
||||||
// Перезапуск с новыми настройками (например, смена профиля)
|
// Перезапуск с новыми настройками (например, смена профиля)
|
||||||
running.set(false)
|
running.set(false)
|
||||||
@@ -399,6 +409,7 @@ class ReflectorClient(
|
|||||||
serverCodecs = info.codecs
|
serverCodecs = info.codecs
|
||||||
callbacks.onServerInfo(info)
|
callbacks.onServerInfo(info)
|
||||||
state = STATE_READY
|
state = STATE_READY
|
||||||
|
everReady = true
|
||||||
callbacks.onState(STATE_READY)
|
callbacks.onState(STATE_READY)
|
||||||
// Сначала сообщаем о себе (версия ПО для дашборда), затем
|
// Сначала сообщаем о себе (версия ПО для дашборда), затем
|
||||||
// выбираем TG для передачи и подписываемся на прослушивание
|
// выбираем TG для передачи и подписываемся на прослушивание
|
||||||
@@ -441,9 +452,17 @@ class ReflectorClient(
|
|||||||
|
|
||||||
ReflectorProtocol.MSG_ERROR -> {
|
ReflectorProtocol.MSG_ERROR -> {
|
||||||
val err = MsgParser.errorMessage(msg.fields)
|
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) {
|
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
|
return false
|
||||||
}
|
}
|
||||||
callbacks.onError(err)
|
callbacks.onError(err)
|
||||||
@@ -452,7 +471,13 @@ class ReflectorClient(
|
|||||||
else -> Unit // неизвестные сообщения игнорируются
|
else -> Unit // неизвестные сообщения игнорируются
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
stopFatal("Ошибка протокола: ${e.message}")
|
if (everReady) {
|
||||||
|
// Сбой после успешного подключения — не фатально, переподключаемся.
|
||||||
|
callbacks.onState(STATE_ERROR, "Ошибка протокола: ${e.message}")
|
||||||
|
abortSockets()
|
||||||
|
} else {
|
||||||
|
stopFatal("Ошибка протокола: ${e.message}")
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -478,7 +503,12 @@ class ReflectorClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun protocolError(detail: String): Boolean {
|
private fun protocolError(detail: String): Boolean {
|
||||||
stopFatal(detail)
|
if (everReady) {
|
||||||
|
callbacks.onState(STATE_ERROR, detail)
|
||||||
|
abortSockets()
|
||||||
|
} else {
|
||||||
|
stopFatal(detail)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user