package com.vgmlr.wedge
import kotlinx.coroutines.*
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.ServerSocket
import java.net.Socket
import org.json.JSONObject
class UsbServerManager(
private val getLocalPassKey: () -> String,
private val onMessageReceived: (String) -> Unit,
private val onStatusChanged: (String, Boolean) -> Unit
) {
private var serverSocket: ServerSocket? = null
private var clientSocket: Socket? = null
private var writer: PrintWriter? = null
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private var isRunning = false
fun startServer() {
if (isRunning) return
isRunning = true
scope.launch {
try {
onStatusChanged("Connecting", false)
serverSocket = ServerSocket(35690).apply {
reuseAddress = true
}
while (isActive) {
val socket = serverSocket?.accept() ?: break
clientSocket = socket
writer = PrintWriter(socket.getOutputStream(), true)
onStatusChanged("Connected", true)
handleClientStream(socket)
}
} catch (_: Exception) {
if (isActive) {
onStatusChanged("Disconnected", false)
}
}
}
}
private suspend fun handleClientStream(socket: Socket) {
withContext(Dispatchers.IO) {
try {
val reader = BufferedReader(InputStreamReader(socket.getInputStream(), "UTF-8"))
var line: String? = null
while (isActive && reader.readLine().also { line = it } != null) {
line?.let { base64Payload ->
try {
val decodedBytes = android.util.Base64.decode(base64Payload, android.util.Base64.NO_WRAP)
val jsonString = String(decodedBytes, Charsets.UTF_8)
val json = JSONObject(jsonString)
val receivedKey = json.getString("key")
val cleanMessage = json.getString("data")
if (receivedKey == getLocalPassKey()) {
withContext(Dispatchers.Main) {
onMessageReceived(cleanMessage)
}
} else {
withContext(Dispatchers.Main) {
onStatusChanged("Pass Key Incorrect", false)
}
}
} catch (_: Exception) {
}
}
}
} catch (_: Exception) {
} finally {
withContext(Dispatchers.Main) {
onStatusChanged("Disconnected", false)
}
writer = null
clientSocket?.close()
}
}
}
fun sendTextMessage(message: String, passKey: String, onSuccess: () -> Unit) {
scope.launch(Dispatchers.IO) {
try {
val json = JSONObject().apply {
put("key", passKey)
put("data", message)
}
val bytes = json.toString().toByteArray(Charsets.UTF_8)
val base64Encoded = android.util.Base64.encodeToString(bytes, android.util.Base64.NO_WRAP)
writer?.println(base64Encoded)
withContext(Dispatchers.Main) {
onSuccess()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun stopServer() {
isRunning = false
scope.launch(Dispatchers.IO) {
try {
clientSocket?.close()
serverSocket?.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}