1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.flightfeather.uav.socket
 
import com.flightfeather.uav.socket.decoder.DataPackageDecoder
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageDecoder
 
/**
 * @author riku
 * Date: 2020/06/02
 * 数据粘包分包解码器
 */
class UAVByteDataDecoder : ByteToMessageDecoder() {
 
    companion object {
        const val BASE_LENGTH = DataPackageDecoder.HEAD_BYTES + DataPackageDecoder.COMMAND_UNIT_BYTES +
                DataPackageDecoder.DEVICE_CODE_BYTES + DataPackageDecoder.DATA_LENGTH + DataPackageDecoder.BCC_BYTES
        const val HEAD1 = 0x01.toByte()
        const val COMMAND_1 = 0x04.toByte()
        const val COMMAND_2 = 0x05.toByte()
        const val HEAD_LENGTH = DataPackageDecoder.HEAD_BYTES + DataPackageDecoder.COMMAND_UNIT_BYTES +
                DataPackageDecoder.DEVICE_CODE_BYTES
    }
 
    override fun decode(p0: ChannelHandlerContext?, p1: ByteBuf?, p2: MutableList<Any>?) {
 
        val dataList = mutableListOf<Byte>()
 
        p1?.let {
            // 可读长度必须大于基本长度
            if (it.readableBytes() >= BASE_LENGTH) {
                // 防止socket字节流攻击
                // 防止,客户端传来的数据过大
                if (it.readableBytes() > 2048) {
                    it.skipBytes(it.readableBytes())
                }
                // 记录包头开始的index
                var beginReader = 0
 
                while (true) {
                    // 获取包头开始的index
                    beginReader = it.readerIndex()
                    // 标记包头开始的index
                    it.markReaderIndex()
                    // 读到了协议的开始标志,结束while循环
                    val b = ByteArray(HEAD_LENGTH)
                    it.readBytes(b)
                    if (b[0] == HEAD1 &&
                        (b[1] == COMMAND_1 || b[1] == COMMAND_2)) {
                        b.forEach {b ->
                            dataList.add(b)
                        }
                        break
                    }
 
                    // 未读到包头,重置到之前记录的包头开始位置
                    // 略过1个字节后,再循环开始读取
                    it.resetReaderIndex()
                    it.readByte()
 
                    //当数据包长度不足时,立刻结束,等待后续数据到达
                    if (it.readableBytes() < BASE_LENGTH) {
                        return
                    }
                }
 
//                ByteArray(1).apply {
//                    it.readBytes(this)
//                }.forEach {b ->
//                    dataList.add(b)
//                }
 
                //数据单元的长度
                val length = getDataUnitLength(it, dataList)
                // 判断请求数据单元数据及[LENGTH_BYTES]个字节的校验码是否到齐
                if (it.readableBytes() < length + DataPackageDecoder.BCC_BYTES) {
                    // 还原读指针
                    it.readerIndex(beginReader)
                    return
                }
 
                //读取数据单元和校验码数据
                ByteArray(length + DataPackageDecoder.BCC_BYTES).apply {
                    it.readBytes(this)
                }.forEach {b ->
                    dataList.add(b)
                }
 
                p2?.add(dataList.toByteArray())
 
            }
        }
    }
 
    /**
     * 获取数据单元长度并将其添加至结果列表中
     */
    private fun getDataUnitLength(p1: ByteBuf, dataList: MutableList<Byte>): Int {
        val sb = StringBuilder()
 
        ByteArray(1).apply {
            p1.readBytes(this)
        }.forEach { b ->
            val a: Int = if (b < 0) {
                b + 256
            } else {
                b.toInt()
            }
 
            sb.append(a.toString(16))
 
            dataList.add(b)
        }
 
        return sb.toString().toInt(16)
    }
}