feat: Enhance packet handling logging to notify number of waiters and catch errors
This commit is contained in:
@@ -104,6 +104,7 @@ class Protocol(
|
||||
|
||||
/**
|
||||
* Start heartbeat to keep connection alive
|
||||
* Как в Архиве - отправляем text "heartbeat"
|
||||
*/
|
||||
private fun startHeartbeat(intervalSeconds: Int) {
|
||||
heartbeatJob?.cancel()
|
||||
@@ -114,10 +115,14 @@ class Protocol(
|
||||
heartbeatJob = scope.launch {
|
||||
while (isActive) {
|
||||
delay(intervalMs)
|
||||
if (webSocket?.send("heartbeat") == true) {
|
||||
log("💓 Heartbeat sent")
|
||||
} else {
|
||||
log("💔 Heartbeat failed to send")
|
||||
try {
|
||||
if (webSocket?.send("heartbeat") == true) {
|
||||
log("💓 Heartbeat sent")
|
||||
} else {
|
||||
log("💔 Heartbeat failed - socket closed or null")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log("💔 Heartbeat error: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,14 +137,18 @@ class Protocol(
|
||||
return
|
||||
}
|
||||
|
||||
// Allow reconnection even if connected (for manual reconnect)
|
||||
if (_state.value == ProtocolState.CONNECTED || _state.value == ProtocolState.AUTHENTICATED) {
|
||||
log("Already connected/authenticated, skipping...")
|
||||
return
|
||||
// Закрываем старый сокет если есть (как в Архиве)
|
||||
webSocket?.let { oldSocket ->
|
||||
try {
|
||||
oldSocket.close(1000, "Reconnecting")
|
||||
log("🔄 Closed old WebSocket before reconnect")
|
||||
} catch (e: Exception) {
|
||||
log("⚠️ Error closing old socket: ${e.message}")
|
||||
}
|
||||
}
|
||||
webSocket = null
|
||||
|
||||
isManuallyClosed = false
|
||||
// Don't reset reconnectAttempts here - it's reset on successful connection in onOpen
|
||||
_state.value = ProtocolState.CONNECTING
|
||||
_lastError.value = null
|
||||
|
||||
@@ -164,6 +173,7 @@ class Protocol(
|
||||
}
|
||||
|
||||
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
|
||||
log("📥 onMessage called - ${bytes.size} bytes")
|
||||
handleMessage(bytes.toByteArray())
|
||||
}
|
||||
|
||||
@@ -172,16 +182,23 @@ class Protocol(
|
||||
}
|
||||
|
||||
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
||||
log("⚠️ WebSocket closing: $code - $reason")
|
||||
log("⚠️ WebSocket closing: code=$code reason='$reason'")
|
||||
log("⚠️ Stack trace at closing:")
|
||||
Thread.currentThread().stackTrace.take(10).forEach {
|
||||
log(" at $it")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
||||
log("❌ WebSocket closed: $code - $reason")
|
||||
log("❌ WebSocket closed: code=$code reason='$reason'")
|
||||
log("❌ State was: ${_state.value}")
|
||||
handleDisconnect()
|
||||
}
|
||||
|
||||
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
||||
log("❌ WebSocket error: ${t.message}")
|
||||
log("❌ WebSocket failure: ${t.message}")
|
||||
log("❌ Response: ${response?.code} ${response?.message}")
|
||||
t.printStackTrace()
|
||||
_lastError.value = t.message
|
||||
handleDisconnect()
|
||||
}
|
||||
@@ -251,7 +268,23 @@ class Protocol(
|
||||
val hexDump = data.take(50).joinToString(" ") { String.format("%02X", it) }
|
||||
log(" Hex: $hexDump${if (data.size > 50) "..." else ""}")
|
||||
|
||||
webSocket?.send(ByteString.of(*data))
|
||||
val socket = webSocket
|
||||
if (socket == null) {
|
||||
log("❌ WebSocket is null, cannot send packet ${packet.getPacketId()}")
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val sent = socket.send(ByteString.of(*data))
|
||||
if (sent) {
|
||||
log("✅ Packet ${packet.getPacketId()} sent successfully")
|
||||
} else {
|
||||
log("❌ Failed to send packet ${packet.getPacketId()} - send() returned false")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log("❌ Exception sending packet ${packet.getPacketId()}: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun flushPacketQueue() {
|
||||
@@ -282,11 +315,15 @@ class Protocol(
|
||||
packet.receive(stream)
|
||||
|
||||
// Notify waiters
|
||||
val waitersCount = packetWaiters[packetId]?.size ?: 0
|
||||
log("📥 Notifying $waitersCount waiter(s) for packet $packetId")
|
||||
|
||||
packetWaiters[packetId]?.forEach { callback ->
|
||||
try {
|
||||
callback(packet)
|
||||
} catch (e: Exception) {
|
||||
log("❌ Error in packet handler: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -301,37 +338,26 @@ class Protocol(
|
||||
handshakeComplete = false
|
||||
handshakeJob?.cancel()
|
||||
heartbeatJob?.cancel()
|
||||
webSocket = null // Обнуляем сокет чтобы connect() мог создать новый
|
||||
|
||||
// Автоматический reconnect (как в Архиве)
|
||||
// Автоматический reconnect (упрощённая логика как в Архиве)
|
||||
if (!isManuallyClosed) {
|
||||
// Логируем потерю соединения
|
||||
if (previousState == ProtocolState.AUTHENTICATED || previousState == ProtocolState.CONNECTED) {
|
||||
log("🔄 Connection lost from $previousState, will reconnect...")
|
||||
reconnectAttempts = 0 // Сбрасываем счётчик при неожиданной потере
|
||||
log("🔄 Connection lost from $previousState, reconnecting...")
|
||||
reconnectAttempts++
|
||||
|
||||
val delay = if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
||||
RECONNECT_INTERVAL
|
||||
} else {
|
||||
// После максимума попыток - ждём дольше
|
||||
reconnectAttempts = 0
|
||||
30000L
|
||||
}
|
||||
|
||||
if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
||||
reconnectAttempts++
|
||||
val delay = RECONNECT_INTERVAL * minOf(reconnectAttempts, 3) // Exponential backoff до 15 секунд
|
||||
log("🔄 Reconnecting in ${delay}ms (attempt $reconnectAttempts/$MAX_RECONNECT_ATTEMPTS)")
|
||||
|
||||
scope.launch {
|
||||
delay(delay)
|
||||
if (!isManuallyClosed) {
|
||||
connect()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("❌ Max reconnect attempts reached, resetting counter...")
|
||||
// Сбрасываем счетчик и пробуем снова через большой интервал
|
||||
reconnectAttempts = 0
|
||||
scope.launch {
|
||||
delay(30000) // 30 секунд перед следующей серией попыток
|
||||
if (!isManuallyClosed) {
|
||||
log("🔄 Restarting reconnection attempts...")
|
||||
connect()
|
||||
}
|
||||
log("🔄 Reconnecting in ${delay}ms (attempt $reconnectAttempts)")
|
||||
|
||||
scope.launch {
|
||||
delay(delay)
|
||||
if (!isManuallyClosed) {
|
||||
connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user