618 lines
22 KiB
Kotlin
618 lines
22 KiB
Kotlin
package cn.trans88.taxiappkotlin.ledok
|
||
|
||
import android.content.Context
|
||
import android.util.Log
|
||
import cn.trans88.taxiappkotlin.R
|
||
import cn.trans88.taxiappkotlin.TaxiApp
|
||
import cn.trans88.taxiappkotlin.logic.network.ConnManger
|
||
import com.google.gson.GsonBuilder
|
||
import com.trs88.kurolibrary.log.KuroLog
|
||
import java.io.BufferedReader
|
||
import java.io.DataOutputStream
|
||
import java.io.File
|
||
import java.io.FileOutputStream
|
||
import java.io.FileReader
|
||
import java.io.IOException
|
||
import java.io.InputStream
|
||
import java.net.ServerSocket
|
||
import java.net.Socket
|
||
import java.util.Timer
|
||
import java.util.TimerTask
|
||
import java.util.concurrent.TimeUnit
|
||
|
||
class TaskSocketServer(private val context: Context, port: Int) {
|
||
companion object {
|
||
val TAG: String = TaskSocketServer::class.java.simpleName
|
||
}
|
||
|
||
var timer: Timer? = null
|
||
|
||
private var file: File? = null
|
||
private var fos: FileOutputStream? = null
|
||
private var dos: DataOutputStream? = null
|
||
private var startFlag = 0
|
||
private var endFlag = 0
|
||
|
||
//private byte[] globleBuff = new byte[1020];
|
||
var m_iCurFileSize: Int = 0 //当前文件的大小
|
||
var m_iCurFileRecvLength: Int = 0 //当前文件接收到的字节
|
||
private val bFileOpr = false
|
||
var jsonBuff: ByteBuffer = ByteBuffer()
|
||
|
||
private var soc: ServerSocket? = null
|
||
private var client: Socket? = null
|
||
private val dir: String? = null
|
||
private var downloadDir: File? = null
|
||
private val prot = 3333
|
||
private var recreate = true
|
||
|
||
fun destroy() {
|
||
Log.i(TAG, "destroy killLive。。。。")
|
||
killLive()
|
||
clear()
|
||
if (client != null) {
|
||
try {
|
||
client!!.close()
|
||
} catch (e: IOException) {
|
||
e.printStackTrace()
|
||
}
|
||
client = null
|
||
}
|
||
try {
|
||
if (soc != null) soc!!.close()
|
||
soc = null
|
||
} catch (e: IOException) {
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
|
||
fun listen() {
|
||
Log.i(TAG, "listen")
|
||
keepLive()
|
||
while (soc != null && !soc!!.isClosed) {
|
||
try {
|
||
//只保持一个链接,新的进来就把老的断开
|
||
val socket = soc!!.accept()
|
||
socket.soTimeout = 5000
|
||
if (client != null) {
|
||
client!!.close()
|
||
}
|
||
client = socket
|
||
Log.i(TAG, "new client is connected")
|
||
clear()
|
||
//edit by ljh@2024/4/28 优化ledOk发节目旧连接没断开,新连接发送不了数据问题
|
||
ThreadProcessor.getInstance().addThread {
|
||
recvDataFromClient()
|
||
}
|
||
} catch (e: Exception) {
|
||
Log.d(TAG, "Exception msg: " + e.message)
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
Log.i(TAG, "server 断开重建。。。。")
|
||
}
|
||
|
||
private fun keepLive() {
|
||
if (timer == null) {
|
||
timer = Timer()
|
||
timer!!.schedule(object : TimerTask() {
|
||
override fun run() {
|
||
if (soc != null && !soc!!.isClosed) {
|
||
Log.i(TAG, "server live 。。。。")
|
||
recreate = false
|
||
} else {
|
||
Log.i(TAG, "server death 。。。。")
|
||
recreate = true
|
||
}
|
||
}
|
||
}, 5000, (30 * 1000).toLong())
|
||
}
|
||
}
|
||
|
||
|
||
private fun killLive() {
|
||
Log.i(TAG, "killLive。。。。")
|
||
if (timer != null) {
|
||
timer!!.cancel()
|
||
timer = null
|
||
}
|
||
}
|
||
|
||
fun sendDataToClient(msg: String) {
|
||
try {
|
||
val bs = msg.toByteArray()
|
||
if (client != null) {
|
||
client!!.getOutputStream().write(bs)
|
||
}
|
||
} catch (e: Exception) {
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
|
||
fun recvDataFromClient() {
|
||
var len = -1
|
||
val buff = ByteArray(4096)
|
||
var input: InputStream? = null
|
||
try {
|
||
input = client!!.getInputStream()
|
||
while ((input.read(buff).also { len = it }) != -1
|
||
) {
|
||
processData(buff, len)
|
||
}
|
||
} catch (e: Exception) {
|
||
e.printStackTrace()
|
||
Log.i(TAG, "出错重置。。。。")
|
||
clear();
|
||
try {
|
||
client?.close();
|
||
} catch (e: IOException) {
|
||
e.printStackTrace();
|
||
}
|
||
} finally {
|
||
clear()
|
||
if (input != null) {
|
||
try {
|
||
input.close()
|
||
} catch (e: IOException) {
|
||
throw RuntimeException(e)
|
||
}
|
||
}
|
||
if (client != null) {
|
||
try {
|
||
client!!.close()
|
||
} catch (e: IOException) {
|
||
throw RuntimeException(e)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fun clear() {
|
||
if (file != null) {
|
||
file!!.delete()
|
||
file = null
|
||
}
|
||
if (fos != null) {
|
||
try {
|
||
fos!!.close()
|
||
fos = null
|
||
} catch (e: IOException) {
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
if (dos != null) {
|
||
try {
|
||
dos!!.close()
|
||
dos = null
|
||
} catch (e: IOException) {
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
startFlag = 0
|
||
endFlag = 0
|
||
m_iCurFileSize = 0
|
||
m_iCurFileRecvLength = 0
|
||
jsonBuff.clear()
|
||
}
|
||
|
||
|
||
private fun processData(buff: ByteArray, len: Int) {
|
||
var i = 0
|
||
while (i < len) {
|
||
if (file != null) {
|
||
//文件已经打开,说明已经收到了fileStart,下面的数据准备写入文件
|
||
val iRestLength = len - i
|
||
// m_iCurFileSize表示 ledOk发过来文件的大小,m_iCurFileRecvLength表示 当前文件接收到的字,累加起来
|
||
val iRestFileLength = m_iCurFileSize - m_iCurFileRecvLength
|
||
// Log.d(
|
||
// TAG,
|
||
// "m_iCurFileSize:$m_iCurFileSize\nm_iCurFileRecvLength:$m_iCurFileRecvLength\niRestFileLength:$iRestFileLength"
|
||
// )
|
||
// Log.d(TAG, "processData: file: ")
|
||
//buff中剩余的字节数 大于 剩余未写入文件的字节数
|
||
if (iRestLength >= iRestFileLength) {
|
||
//并且剩余文件未写入字节数 大于 0
|
||
if (iRestFileLength > 0) {
|
||
//直接将iRestFileLength长度字节数写入文件,buff索引向后移动iRestFileLength个字节
|
||
try {
|
||
val restBuff = ByteArray(iRestFileLength)
|
||
System.arraycopy(buff, i, restBuff, 0, iRestFileLength)
|
||
//// Log.i(TAG,"BS:"+Arrays.toString(restBuff));
|
||
if (fos == null) {
|
||
fos = FileOutputStream(file)
|
||
if (dos == null) {
|
||
dos = DataOutputStream(fos)
|
||
}
|
||
//Log.i(TAG,"BS:"+Arrays.toString(restBuff));
|
||
KuroLog.i("TAG:processData:0")
|
||
dos!!.write(restBuff)
|
||
} else {
|
||
if (dos == null) {
|
||
dos = DataOutputStream(fos)
|
||
}
|
||
//Log.i(TAG,"BS:"+Arrays.toString(restBuff));\
|
||
KuroLog.i("TAG:processData:1")
|
||
dos!!.write(restBuff)
|
||
}
|
||
m_iCurFileRecvLength += iRestFileLength
|
||
i += iRestFileLength
|
||
//文件写完了,关闭当前文件
|
||
startFlag = 0
|
||
} catch (e: Exception) {
|
||
//Log.i(tag, "10000000000000000000");
|
||
e.printStackTrace()
|
||
}
|
||
} else {
|
||
//Log.i(tag, "iRestFileLength <= 0");
|
||
if (iRestFileLength < 0) {
|
||
Log.i(TAG, "iRestFileLength < 0")
|
||
}
|
||
}
|
||
} else {
|
||
try {
|
||
val restBuff = ByteArray(iRestLength)
|
||
//// Log.i(TAG,"BS:"+Arrays.toString(restBuff));
|
||
System.arraycopy(buff, i, restBuff, 0, iRestLength)
|
||
//Log.i(tag, "00");
|
||
if (file != null) {
|
||
//Log.i(tag, "01");
|
||
if (fos == null) {
|
||
fos = FileOutputStream(file)
|
||
if (dos == null) {
|
||
dos = DataOutputStream(fos)
|
||
}
|
||
KuroLog.i("TAG:processData:2")
|
||
dos!!.write(restBuff)
|
||
} else {
|
||
if (dos == null) {
|
||
dos = DataOutputStream(fos)
|
||
}
|
||
// KuroLog.i("TAG:processData:3");
|
||
dos!!.write(restBuff)
|
||
}
|
||
}
|
||
m_iCurFileRecvLength += iRestLength
|
||
} catch (e: Exception) {
|
||
//Log.i(tag, "1111111111111111111111111");
|
||
e.printStackTrace()
|
||
}
|
||
return
|
||
}
|
||
}
|
||
//
|
||
if (startFlag == 0) {
|
||
if (buff[i] == '{'.toByte()) {
|
||
startFlag = 1
|
||
jsonBuff.append(buff[i])
|
||
}
|
||
} else if (startFlag == 1) {
|
||
if (buff[i] == '"'.toByte()) {
|
||
startFlag = 2
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 2) {
|
||
if (buff[i] == '_'.toByte()) {
|
||
startFlag = 3
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 3) {
|
||
if (buff[i] == 't'.toByte()) {
|
||
startFlag = 4
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 4) {
|
||
if (buff[i] == 'y'.toByte()) {
|
||
startFlag = 5
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 5) {
|
||
if (buff[i] == 'p'.toByte()) {
|
||
startFlag = 6
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 6) {
|
||
if (buff[i] == 'e'.toByte()) {
|
||
startFlag = 7
|
||
jsonBuff.append(buff[i])
|
||
} else {
|
||
startFlag = 0
|
||
jsonBuff.clear()
|
||
}
|
||
} else if (startFlag == 7) {
|
||
if (endFlag == 0) {
|
||
if (buff[i] == 'x'.toByte()) {
|
||
endFlag = 1
|
||
}
|
||
} else if (endFlag == 1) {
|
||
endFlag = if (buff[i] == 'i'.toByte()) {
|
||
2
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 2) {
|
||
endFlag = if (buff[i] == 'x'.toByte()) {
|
||
3
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 3) {
|
||
endFlag = if (buff[i] == 'u'.toByte()) {
|
||
4
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 4) {
|
||
endFlag = if (buff[i] == 'n'.toByte()) {
|
||
5
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 5) {
|
||
endFlag = if (buff[i] == '1'.toByte()) {
|
||
6 //jsonObject结束
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 6) {
|
||
endFlag = if (buff[i] == '"'.toByte()) {
|
||
7 //jsonObject结束
|
||
} else {
|
||
0
|
||
}
|
||
} else if (endFlag == 7) {
|
||
endFlag = if (buff[i] == '}'.toByte()) {
|
||
8 //jsonObject结束
|
||
} else {
|
||
0
|
||
}
|
||
}
|
||
jsonBuff.append(buff[i])
|
||
if (endFlag == 8) {
|
||
val json = String(jsonBuff.buff, 0, jsonBuff.len())
|
||
processPackage(json)
|
||
endFlag = 0
|
||
startFlag = endFlag
|
||
jsonBuff.clear()
|
||
}
|
||
}
|
||
i++
|
||
}
|
||
}
|
||
|
||
fun processPackage(json: String?) {
|
||
if (json != null) {
|
||
try {
|
||
val gson = GsonBuilder().serializeNulls().create()
|
||
val cmd = gson.fromJson(json, JsonCommand::class.java)
|
||
if (cmd._type == "consult") {
|
||
Log.d(TAG, "processPackage([json]): consult: $json")
|
||
idList1 = cmd.idList
|
||
ackList(cmd.idList)
|
||
} else if (cmd._type == "proStart") {
|
||
Log.d(TAG, "processPackage([json]): proStart: $json")
|
||
} else if (cmd._type == "proEnd") {
|
||
Log.d(TAG, "processPackage([json]): proEnd: $json")
|
||
val ack = "{\"_type\":\"AckSuccess\"}"
|
||
sendDataToClient(ack)
|
||
client?.close()
|
||
Log.d(TAG, "processPackage([json]): ack: $ack")
|
||
//文件接收完成,可以开始播放
|
||
LedOkCommands.startLedOkActivity()
|
||
} else if (cmd._type == "fileStart") {
|
||
Log.d(TAG, "processPackage([json]): fileStart: $json")
|
||
m_iCurFileSize = cmd.size
|
||
m_iCurFileRecvLength = 0
|
||
if (!cmd.id!!.isEmpty() && file == null) {
|
||
if (!downloadDir?.exists()!!) {
|
||
downloadDir?.mkdirs();
|
||
}
|
||
var path = "${downloadDir?.absolutePath}/${cmd.id}"
|
||
file = File(path);
|
||
if (!file!!.exists()) {
|
||
Log.i(TAG, "create file :" + path);
|
||
file!!.createNewFile();
|
||
}
|
||
file!!.setWritable(true, true);
|
||
} else if (!cmd.id!!.isEmpty() && file != null) {
|
||
if (!file!!.canWrite()) {
|
||
file!!.setWritable(true, true)
|
||
}
|
||
}
|
||
} else if (cmd._type == "fileEnd") {
|
||
Log.d(TAG, "processPackage([json]): fileEnd: $json")
|
||
if (dos != null) {
|
||
dos!!.flush()
|
||
//将数据同步到达物理存储设备
|
||
val fd = fos!!.fd
|
||
fd.sync()
|
||
dos!!.close()
|
||
}
|
||
if (fos != null) fos!!.close()
|
||
file!!.setWritable(false, true);
|
||
fos = null
|
||
dos = null
|
||
file = null
|
||
//TaskProcessor.getInstance(context).updateSourceFile(new SourceFile(cmd.id, servant.getCanUsedPath(context), FileState.Is_Downloaded));
|
||
}
|
||
// else if (cmd._type == "BindAccount") {
|
||
// Log.d(TAG, "processPackage: BindAccount")
|
||
// val server = cmd.server!!
|
||
// val tlsServer = cmd.tlsServer!!
|
||
// val accountIdToken = cmd.accountIdToken!!
|
||
// val bindModel = BindModel("", accountIdToken, server, tlsServer)!!
|
||
// if (bindModel?.server != null && bindModel?.server != "") {
|
||
// bindModel?.server = bindModel?.server + "/"
|
||
// }
|
||
// if (bindModel?.server != null && bindModel.server != "") {
|
||
// bindModel.tlsServer = bindModel.tlsServer + "/"
|
||
// }
|
||
// val mbindAccount = ConnManger.mbindAccount(bindModel)
|
||
// if (mbindAccount == true) {
|
||
// val ack = "{\"_type\":\"AckSuccess\"}"
|
||
// sendDataToClient(ack)
|
||
// } else {
|
||
// val ack = "{\"_type\":\"AckFailed\"}"
|
||
// sendDataToClient(ack)
|
||
// }
|
||
// client?.close()
|
||
// }
|
||
} catch (e: Exception) {
|
||
Log.i(TAG, "error:" + e.message)
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
}
|
||
|
||
fun ackList(list: List<String>?) {
|
||
if (list.isNullOrEmpty()) {
|
||
Log.i(TAG, "consult is empty")
|
||
return
|
||
}
|
||
val downloadList: MutableList<String> = ArrayList()
|
||
for (id in list) {
|
||
val file = File("${downloadDir?.absolutePath}/${id}")
|
||
if (id == "program" || !file.exists()) {
|
||
downloadList.add(id)
|
||
|
||
}
|
||
}
|
||
var sl = ""
|
||
for (i in downloadList.indices) {
|
||
sl = if (i == 0) {
|
||
sl + "\"" + downloadList[i] + "\""
|
||
} else {
|
||
sl + ",\"" + downloadList[i] + "\""
|
||
}
|
||
}
|
||
val ack = "{\"_type\":\"consult\",\"idList\":[$sl]}"
|
||
Log.d(TAG, "processPackage([json]): ack: $ack")
|
||
sendDataToClient(ack)
|
||
//发送出去
|
||
}
|
||
|
||
inner class ByteBuffer {
|
||
var buff: ByteArray
|
||
private val unit = 3000
|
||
private var size: Int
|
||
private var index: Int
|
||
|
||
init {
|
||
buff = ByteArray(unit)
|
||
size = unit
|
||
index = 0
|
||
}
|
||
|
||
fun append(b: Byte) {
|
||
if (index >= size) {
|
||
Log.i(TAG, "================ index of ByteBuffer > size===============")
|
||
size = size + unit
|
||
val temp = ByteArray(size)
|
||
System.arraycopy(buff, 0, temp, 0, index)
|
||
buff = temp
|
||
}
|
||
buff[index] = b
|
||
index++
|
||
}
|
||
|
||
fun clear() {
|
||
buff = ByteArray(unit)
|
||
size = unit
|
||
index = 0
|
||
}
|
||
|
||
fun len(): Int {
|
||
return index
|
||
}
|
||
}
|
||
|
||
inner class JsonCommand {
|
||
var _type: String? = null
|
||
var proName: String? = null
|
||
var proSize: Int = 0
|
||
var zVer: String? = null
|
||
var id: String? = null
|
||
var relative_path: String? = null
|
||
var size: Int = 0
|
||
var data: String? = null
|
||
var _id: String? = null
|
||
var idList: List<String>? = null
|
||
var task: Task? = null
|
||
|
||
// var bindModel: cn.trans88.taxiappkotlin.ledok.BindModel? = null
|
||
var accountIdToken: String? = null
|
||
var server: String? = null
|
||
var tlsServer: String? = null
|
||
}
|
||
|
||
var idList1: List<String>? = null
|
||
|
||
init {
|
||
downloadDir =
|
||
File(TaxiApp.instance().filesDir, TaxiApp.instance().getString(R.string.dir_program))
|
||
Log.d(TAG, "downloadDir: $downloadDir")
|
||
|
||
while (recreate) {
|
||
try {
|
||
// if (soc == null) {
|
||
// destroy()
|
||
soc = ServerSocket(port)
|
||
recreate = false
|
||
// }
|
||
Log.i(TAG, "create...... ")
|
||
} catch (e: Exception) {
|
||
Log.i(TAG, e.message + "...............")
|
||
try {
|
||
TimeUnit.SECONDS.sleep(1)
|
||
} catch (interruptedException: InterruptedException) {
|
||
interruptedException.printStackTrace()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fun readFileContent(fileName: String?): String? {
|
||
val file = File(fileName)
|
||
if (!file.exists()) {
|
||
return null
|
||
}
|
||
var reader: BufferedReader? = null
|
||
val sbf = StringBuffer()
|
||
try {
|
||
reader = BufferedReader(FileReader(file))
|
||
var tempStr: String?
|
||
while ((reader.readLine().also { tempStr = it }) != null) {
|
||
sbf.append(tempStr)
|
||
}
|
||
reader.close()
|
||
return sbf.toString()
|
||
} catch (e: IOException) {
|
||
e.printStackTrace()
|
||
} finally {
|
||
if (reader != null) {
|
||
try {
|
||
reader.close()
|
||
} catch (e1: IOException) {
|
||
e1.printStackTrace()
|
||
}
|
||
}
|
||
}
|
||
return sbf.toString()
|
||
}
|
||
|
||
}
|