feat: Enhance logging and debugging capabilities across Protocol and UI components
This commit is contained in:
@@ -24,7 +24,10 @@ enum class ProtocolState {
|
||||
* Protocol client for Rosetta Messenger
|
||||
* Handles WebSocket connection and packet exchange with server
|
||||
*/
|
||||
class Protocol(private val serverAddress: String) {
|
||||
class Protocol(
|
||||
private val serverAddress: String,
|
||||
private val logger: (String) -> Unit = {}
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "RosettaProtocol"
|
||||
private const val RECONNECT_INTERVAL = 10000L // 10 seconds
|
||||
@@ -32,6 +35,11 @@ class Protocol(private val serverAddress: String) {
|
||||
private const val HANDSHAKE_TIMEOUT = 10000L // 10 seconds
|
||||
}
|
||||
|
||||
private fun log(message: String) {
|
||||
Log.d(TAG, message)
|
||||
logger(message)
|
||||
}
|
||||
|
||||
private val client = OkHttpClient.Builder()
|
||||
.readTimeout(0, TimeUnit.MILLISECONDS)
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
@@ -75,7 +83,7 @@ class Protocol(private val serverAddress: String) {
|
||||
// Register handshake response handler
|
||||
waitPacket(0x00) { packet ->
|
||||
if (packet is PacketHandshake) {
|
||||
Log.d(TAG, "✅ Handshake response received, protocol version: ${packet.protocolVersion}")
|
||||
log("✅ Handshake response received, protocol version: ${packet.protocolVersion}")
|
||||
handshakeJob?.cancel()
|
||||
handshakeComplete = true
|
||||
_state.value = ProtocolState.AUTHENTICATED
|
||||
@@ -89,7 +97,7 @@ class Protocol(private val serverAddress: String) {
|
||||
*/
|
||||
fun connect() {
|
||||
if (_state.value == ProtocolState.CONNECTING || _state.value == ProtocolState.CONNECTED) {
|
||||
Log.d(TAG, "Already connecting or connected")
|
||||
log("Already connecting or connected")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -97,7 +105,7 @@ class Protocol(private val serverAddress: String) {
|
||||
_state.value = ProtocolState.CONNECTING
|
||||
_lastError.value = null
|
||||
|
||||
Log.d(TAG, "🔌 Connecting to: $serverAddress")
|
||||
log("🔌 Connecting to: $serverAddress")
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(serverAddress)
|
||||
@@ -105,7 +113,7 @@ class Protocol(private val serverAddress: String) {
|
||||
|
||||
webSocket = client.newWebSocket(request, object : WebSocketListener() {
|
||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||
Log.d(TAG, "✅ WebSocket connected")
|
||||
log("✅ WebSocket connected")
|
||||
reconnectAttempts = 0
|
||||
_state.value = ProtocolState.CONNECTED
|
||||
|
||||
@@ -122,20 +130,20 @@ class Protocol(private val serverAddress: String) {
|
||||
}
|
||||
|
||||
override fun onMessage(webSocket: WebSocket, text: String) {
|
||||
Log.d(TAG, "Received text message (unexpected): $text")
|
||||
log("Received text message (unexpected): $text")
|
||||
}
|
||||
|
||||
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
||||
Log.d(TAG, "WebSocket closing: $code - $reason")
|
||||
log("WebSocket closing: $code - $reason")
|
||||
}
|
||||
|
||||
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
||||
Log.d(TAG, "WebSocket closed: $code - $reason")
|
||||
log("WebSocket closed: $code - $reason")
|
||||
handleDisconnect()
|
||||
}
|
||||
|
||||
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
||||
Log.e(TAG, "❌ WebSocket error: ${t.message}")
|
||||
log("❌ WebSocket error: ${t.message}")
|
||||
_lastError.value = t.message
|
||||
handleDisconnect()
|
||||
}
|
||||
@@ -146,16 +154,16 @@ class Protocol(private val serverAddress: String) {
|
||||
* Start handshake with server
|
||||
*/
|
||||
fun startHandshake(publicKey: String, privateHash: String) {
|
||||
Log.d(TAG, "🤝 Starting handshake...")
|
||||
Log.d(TAG, " Public key: ${publicKey.take(20)}...")
|
||||
Log.d(TAG, " Private hash: ${privateHash.take(20)}...")
|
||||
log("🤝 Starting handshake...")
|
||||
log(" Public key: ${publicKey.take(20)}...")
|
||||
log(" Private hash: ${privateHash.take(20)}...")
|
||||
|
||||
// Save credentials for reconnection
|
||||
lastPublicKey = publicKey
|
||||
lastPrivateHash = privateHash
|
||||
|
||||
if (_state.value != ProtocolState.CONNECTED && _state.value != ProtocolState.AUTHENTICATED) {
|
||||
Log.d(TAG, "Not connected, will handshake after connection")
|
||||
log("Not connected, will handshake after connection")
|
||||
connect()
|
||||
return
|
||||
}
|
||||
@@ -175,7 +183,7 @@ class Protocol(private val serverAddress: String) {
|
||||
handshakeJob = scope.launch {
|
||||
delay(HANDSHAKE_TIMEOUT)
|
||||
if (!handshakeComplete) {
|
||||
Log.e(TAG, "❌ Handshake timeout")
|
||||
log("❌ Handshake timeout")
|
||||
_lastError.value = "Handshake timeout"
|
||||
disconnect()
|
||||
}
|
||||
@@ -188,7 +196,7 @@ class Protocol(private val serverAddress: String) {
|
||||
*/
|
||||
fun sendPacket(packet: Packet) {
|
||||
if (!handshakeComplete && packet !is PacketHandshake) {
|
||||
Log.d(TAG, "📦 Queueing packet: ${packet.getPacketId()}")
|
||||
log("📦 Queueing packet: ${packet.getPacketId()}")
|
||||
packetQueue.add(packet)
|
||||
return
|
||||
}
|
||||
@@ -199,13 +207,13 @@ class Protocol(private val serverAddress: String) {
|
||||
val stream = packet.send()
|
||||
val data = stream.getStream()
|
||||
|
||||
Log.d(TAG, "📤 Sending packet: ${packet.getPacketId()} (${data.size} bytes)")
|
||||
log("📤 Sending packet: ${packet.getPacketId()} (${data.size} bytes)")
|
||||
|
||||
webSocket?.send(ByteString.of(*data))
|
||||
}
|
||||
|
||||
private fun flushPacketQueue() {
|
||||
Log.d(TAG, "📬 Flushing ${packetQueue.size} queued packets")
|
||||
log("📬 Flushing ${packetQueue.size} queued packets")
|
||||
val packets = packetQueue.toList()
|
||||
packetQueue.clear()
|
||||
packets.forEach { sendPacketDirect(it) }
|
||||
@@ -216,11 +224,11 @@ class Protocol(private val serverAddress: String) {
|
||||
val stream = Stream(data)
|
||||
val packetId = stream.readInt16()
|
||||
|
||||
Log.d(TAG, "📥 Received packet: $packetId")
|
||||
log("📥 Received packet: $packetId")
|
||||
|
||||
val packetFactory = supportedPackets[packetId]
|
||||
if (packetFactory == null) {
|
||||
Log.w(TAG, "Unknown packet ID: $packetId")
|
||||
log("⚠️ Unknown packet ID: $packetId")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -232,11 +240,11 @@ class Protocol(private val serverAddress: String) {
|
||||
try {
|
||||
callback(packet)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error in packet handler: ${e.message}")
|
||||
log("❌ Error in packet handler: ${e.message}")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error parsing packet: ${e.message}")
|
||||
log("❌ Error parsing packet: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,14 +255,14 @@ class Protocol(private val serverAddress: String) {
|
||||
|
||||
if (!isManuallyClosed && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
||||
reconnectAttempts++
|
||||
Log.d(TAG, "🔄 Reconnecting in ${RECONNECT_INTERVAL}ms (attempt $reconnectAttempts/$MAX_RECONNECT_ATTEMPTS)")
|
||||
log("🔄 Reconnecting in ${RECONNECT_INTERVAL}ms (attempt $reconnectAttempts/$MAX_RECONNECT_ATTEMPTS)")
|
||||
|
||||
scope.launch {
|
||||
delay(RECONNECT_INTERVAL)
|
||||
connect()
|
||||
}
|
||||
} else if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
Log.e(TAG, "❌ Max reconnect attempts reached")
|
||||
log("❌ Max reconnect attempts reached")
|
||||
_lastError.value = "Unable to connect to server"
|
||||
}
|
||||
}
|
||||
@@ -277,7 +285,7 @@ class Protocol(private val serverAddress: String) {
|
||||
* Disconnect from server
|
||||
*/
|
||||
fun disconnect() {
|
||||
Log.d(TAG, "Disconnecting...")
|
||||
log("Disconnecting...")
|
||||
isManuallyClosed = true
|
||||
handshakeJob?.cancel()
|
||||
webSocket?.close(1000, "User disconnected")
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.rosetta.messenger.network
|
||||
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Singleton manager for Protocol instance
|
||||
@@ -15,13 +19,31 @@ object ProtocolManager {
|
||||
|
||||
private var protocol: Protocol? = null
|
||||
|
||||
// Debug logs for dev console
|
||||
private val _debugLogs = MutableStateFlow<List<String>>(emptyList())
|
||||
val debugLogs: StateFlow<List<String>> = _debugLogs.asStateFlow()
|
||||
|
||||
private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault())
|
||||
|
||||
fun addLog(message: String) {
|
||||
val timestamp = dateFormat.format(Date())
|
||||
val logLine = "[$timestamp] $message"
|
||||
Log.d(TAG, logLine)
|
||||
_debugLogs.value = (_debugLogs.value + logLine).takeLast(100)
|
||||
}
|
||||
|
||||
fun clearLogs() {
|
||||
_debugLogs.value = emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create Protocol instance
|
||||
*/
|
||||
fun getProtocol(): Protocol {
|
||||
if (protocol == null) {
|
||||
Log.d(TAG, "Creating new Protocol instance")
|
||||
protocol = Protocol(SERVER_ADDRESS)
|
||||
addLog("Creating new Protocol instance")
|
||||
addLog("Server: $SERVER_ADDRESS")
|
||||
protocol = Protocol(SERVER_ADDRESS) { msg -> addLog(msg) }
|
||||
}
|
||||
return protocol!!
|
||||
}
|
||||
@@ -42,6 +64,7 @@ object ProtocolManager {
|
||||
* Connect to server
|
||||
*/
|
||||
fun connect() {
|
||||
addLog("Connect requested")
|
||||
getProtocol().connect()
|
||||
}
|
||||
|
||||
@@ -49,7 +72,9 @@ object ProtocolManager {
|
||||
* Authenticate with server
|
||||
*/
|
||||
fun authenticate(publicKey: String, privateHash: String) {
|
||||
Log.d(TAG, "Authenticating...")
|
||||
addLog("Authenticate called")
|
||||
addLog("PublicKey: ${publicKey.take(30)}...")
|
||||
addLog("PrivateHash: ${privateHash.take(20)}...")
|
||||
getProtocol().startHandshake(publicKey, privateHash)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user