2023-10-25 11:23:11 +08:00
|
|
|
|
package message
|
|
|
|
|
|
2023-10-25 17:03:48 +08:00
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
2023-11-01 17:46:24 +08:00
|
|
|
|
"strings"
|
2023-10-25 17:03:48 +08:00
|
|
|
|
)
|
2023-10-25 11:23:11 +08:00
|
|
|
|
|
|
|
|
|
//RSSP-1 V1.0 铁路信号安全通信协议
|
|
|
|
|
|
|
|
|
|
// RsspHead rssp报文头
|
|
|
|
|
type RsspHead struct {
|
|
|
|
|
//报文头-协议交互类别(1Byte)
|
|
|
|
|
Pic byte
|
|
|
|
|
//报文头-报文类别(1Byte)
|
|
|
|
|
Mc byte
|
|
|
|
|
//报文头-源地址(2Byte)
|
|
|
|
|
Sa uint16
|
|
|
|
|
//报文头-目地址(2Byte)
|
|
|
|
|
Da uint16
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 17:46:24 +08:00
|
|
|
|
func (h *RsspHead) Parse(buf []byte) bool {
|
|
|
|
|
if len(buf) < 6 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
h.decode(buf)
|
|
|
|
|
return true
|
|
|
|
|
}
|
2023-10-25 17:03:48 +08:00
|
|
|
|
func (h *RsspHead) Type() RsspType {
|
|
|
|
|
return h.Mc
|
|
|
|
|
}
|
|
|
|
|
func (h *RsspHead) decode(buf []byte) {
|
|
|
|
|
ri := 0
|
|
|
|
|
//报文头
|
|
|
|
|
h.Pic = buf[ri]
|
|
|
|
|
ri++
|
|
|
|
|
h.Mc = buf[ri]
|
|
|
|
|
ri++
|
|
|
|
|
h.Sa = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
ri += 2
|
|
|
|
|
h.Da = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
ri += 2
|
|
|
|
|
}
|
|
|
|
|
func (h *RsspHead) encode() []byte {
|
|
|
|
|
data := make([]byte, 0, 6)
|
|
|
|
|
//报文头
|
|
|
|
|
data = append(data, h.Pic)
|
|
|
|
|
data = append(data, h.Mc)
|
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, h.Sa)
|
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, h.Da)
|
|
|
|
|
//
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
2023-11-01 17:46:24 +08:00
|
|
|
|
// RsspPackCrc16Check RSSP报文CRC16校验
|
|
|
|
|
func RsspPackCrc16Check(pack []byte) bool {
|
|
|
|
|
if len(pack) <= 2 { //报文长度不够,校验不通过
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
pack16 := binary.LittleEndian.Uint16(pack[len(pack)-2:])
|
|
|
|
|
crc16 := RsspCrc16(pack[:len(pack)-2])
|
|
|
|
|
//
|
|
|
|
|
return crc16 == pack16
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
2023-10-25 11:23:11 +08:00
|
|
|
|
// RsspRsd 实时安全数据包
|
|
|
|
|
type RsspRsd struct {
|
|
|
|
|
RsspHead
|
2023-11-02 14:37:50 +08:00
|
|
|
|
//安全校验域-序列号(4Byte),可以是一个随时间周期变化的计数器
|
2023-10-25 11:23:11 +08:00
|
|
|
|
Sn uint32
|
|
|
|
|
//安全校验域-安全数据长度(2Byte)
|
|
|
|
|
Sdl uint16
|
|
|
|
|
//安全校验域-安全校验通道1(4Byte)
|
|
|
|
|
Svc1 uint32
|
|
|
|
|
//安全校验域-安全校验通道2(4Byte)
|
|
|
|
|
Svc2 uint32
|
|
|
|
|
//用户数据包-安全应用数据(总字节数480)
|
|
|
|
|
Sad []byte
|
|
|
|
|
//报文尾-CRC16(2Byte)
|
|
|
|
|
Crc16 uint16
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r *RsspRsd) Encode() []byte {
|
|
|
|
|
data := make([]byte, 0, 6+14+len(r.Sad)+2)
|
|
|
|
|
//报文头
|
2023-10-25 17:03:48 +08:00
|
|
|
|
data = append(data, r.RsspHead.encode()...)
|
2023-10-25 11:23:11 +08:00
|
|
|
|
//安全校验域
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Sn)
|
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, r.Sdl)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Svc1)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Svc2)
|
|
|
|
|
//用户数据包
|
|
|
|
|
data = append(data, r.Sad...)
|
|
|
|
|
//报文尾-CRC16
|
2023-10-30 14:32:49 +08:00
|
|
|
|
r.Crc16 = RsspCrc16(data)
|
2023-10-25 11:23:11 +08:00
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
|
|
|
|
|
//
|
|
|
|
|
return data
|
|
|
|
|
}
|
2023-10-25 17:03:48 +08:00
|
|
|
|
func (r *RsspRsd) Decode(buf []byte) error {
|
|
|
|
|
//报文头
|
|
|
|
|
r.RsspHead.decode(buf)
|
|
|
|
|
ri := 6
|
|
|
|
|
//安全校验域
|
|
|
|
|
r.Sn = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.Sdl = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
ri += 2
|
|
|
|
|
r.Svc1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.Svc2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
//用户数据
|
|
|
|
|
sadLen := int(r.Sdl) - 8
|
|
|
|
|
r.Sad = buf[ri : ri+sadLen]
|
|
|
|
|
ri += sadLen
|
|
|
|
|
//报文尾
|
|
|
|
|
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
//
|
2023-10-25 11:23:11 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 17:03:48 +08:00
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-10-25 11:23:11 +08:00
|
|
|
|
// RsspSse 时序校正请求包
|
|
|
|
|
type RsspSse struct {
|
|
|
|
|
RsspHead
|
|
|
|
|
//安全校验域-序列号(4Byte)
|
|
|
|
|
Sn uint32
|
|
|
|
|
//安全校验域-时序校正请求通道1(4Byte)
|
|
|
|
|
SeqEnq1 uint32
|
|
|
|
|
//安全校验域-时序校正请求通道2(4Byte)
|
|
|
|
|
SeqEnq2 uint32
|
|
|
|
|
//报文尾-CRC16(2Byte)
|
|
|
|
|
Crc16 uint16
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 17:03:48 +08:00
|
|
|
|
func (r *RsspSse) Encode() []byte {
|
|
|
|
|
data := make([]byte, 0, 20)
|
|
|
|
|
//报文头
|
|
|
|
|
data = append(data, r.RsspHead.encode()...)
|
|
|
|
|
//安全校验域
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Sn)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq1)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq2)
|
|
|
|
|
//报文尾-CRC16
|
2023-10-30 14:32:49 +08:00
|
|
|
|
r.Crc16 = RsspCrc16(data)
|
2023-10-25 17:03:48 +08:00
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
func (r *RsspSse) Decode(buf []byte) error {
|
|
|
|
|
//报文头
|
|
|
|
|
r.RsspHead.decode(buf)
|
|
|
|
|
//安全校验域
|
|
|
|
|
ri := 6
|
|
|
|
|
r.Sn = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.SeqEnq1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.SeqEnq2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
//报文尾
|
|
|
|
|
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
//
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-10-25 11:23:11 +08:00
|
|
|
|
// RsspSsr 时序校正应答包,用于回应SSE
|
|
|
|
|
type RsspSsr struct {
|
|
|
|
|
RsspHead
|
|
|
|
|
//安全校验域-应答方的序列号(4Byte)
|
|
|
|
|
SrSn uint32
|
|
|
|
|
//安全校验域-请求方的序列号(4Byte)
|
|
|
|
|
SeSn uint32
|
|
|
|
|
//安全校验域-时序初始化通道1(4Byte)
|
|
|
|
|
Tic1 uint32
|
|
|
|
|
//安全校验域-时序初始化通道2(4Byte)
|
|
|
|
|
Tic2 uint32
|
|
|
|
|
//安全校验域-数据版本号(1Byte)
|
|
|
|
|
Dvn byte
|
|
|
|
|
//报文尾-CRC16(2Byte)
|
|
|
|
|
Crc16 uint16
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 17:03:48 +08:00
|
|
|
|
func (r *RsspSsr) Encode() []byte {
|
|
|
|
|
data := make([]byte, 0, 25)
|
|
|
|
|
//报文头
|
|
|
|
|
data = append(data, r.RsspHead.encode()...)
|
|
|
|
|
//安全校验域
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.SrSn)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.SeSn)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Tic1)
|
|
|
|
|
data = binary.LittleEndian.AppendUint32(data, r.Tic2)
|
|
|
|
|
data = append(data, r.Dvn)
|
|
|
|
|
//报文尾-CRC16
|
2023-10-30 14:32:49 +08:00
|
|
|
|
r.Crc16 = RsspCrc16(data)
|
2023-10-25 17:03:48 +08:00
|
|
|
|
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
func (r *RsspSsr) Decode(buf []byte) error {
|
|
|
|
|
//报文头
|
|
|
|
|
r.RsspHead.decode(buf)
|
|
|
|
|
//安全校验域
|
|
|
|
|
ri := 6
|
|
|
|
|
r.SrSn = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.SeSn = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.Tic1 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.Tic2 = binary.LittleEndian.Uint32(buf[ri : ri+4])
|
|
|
|
|
ri += 4
|
|
|
|
|
r.Dvn = buf[ri]
|
|
|
|
|
ri += 1
|
|
|
|
|
//报文尾
|
|
|
|
|
r.Crc16 = binary.LittleEndian.Uint16(buf[ri : ri+2])
|
|
|
|
|
//
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type RsspCodec interface {
|
|
|
|
|
Encode() []byte
|
|
|
|
|
Decode(buf []byte) error
|
|
|
|
|
}
|
|
|
|
|
type Rssper interface {
|
|
|
|
|
Type() RsspType
|
|
|
|
|
}
|
|
|
|
|
type RsspType = byte
|
|
|
|
|
|
2023-11-01 17:46:24 +08:00
|
|
|
|
const ( //报文类型
|
2023-10-25 17:03:48 +08:00
|
|
|
|
RSD_A = RsspType(0x80)
|
|
|
|
|
RSD_B = RsspType(0x81)
|
|
|
|
|
SSE = RsspType(0x90)
|
|
|
|
|
SSR = RsspType(0x91)
|
|
|
|
|
)
|
|
|
|
|
|
2023-11-01 17:46:24 +08:00
|
|
|
|
// RsspHeadMcCheck 报文类型检测
|
|
|
|
|
func RsspHeadMcCheck(head *RsspHead) bool {
|
|
|
|
|
switch head.Mc {
|
2023-11-02 09:24:11 +08:00
|
|
|
|
case RSD_A:
|
|
|
|
|
return true
|
|
|
|
|
case RSD_B:
|
|
|
|
|
return true
|
|
|
|
|
case SSR:
|
|
|
|
|
return true
|
|
|
|
|
case SSE:
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return true
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PicType = byte
|
|
|
|
|
|
|
|
|
|
const ( //协议交互类别
|
|
|
|
|
PIC_MASTER = PicType(0x01) //主机发送的安全数据
|
|
|
|
|
PIC_SLAVE = PicType(0x02) //备机发送的安全数据
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// RsspHeadPicCheck 协议交互类别检测
|
|
|
|
|
func RsspHeadPicCheck(head *RsspHead) bool {
|
|
|
|
|
switch head.Pic {
|
2023-11-02 09:24:11 +08:00
|
|
|
|
case PIC_MASTER:
|
|
|
|
|
return true
|
|
|
|
|
case PIC_SLAVE:
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return true
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-02 09:24:11 +08:00
|
|
|
|
// ParseRsspPack 解析已经校验的RSSP数据包
|
|
|
|
|
func ParseRsspPack(ph *RsspHead, pack []byte) Rssper {
|
2023-10-25 17:03:48 +08:00
|
|
|
|
//
|
|
|
|
|
var codec RsspCodec
|
|
|
|
|
switch ph.Mc {
|
2023-11-02 09:24:11 +08:00
|
|
|
|
case RSD_A:
|
|
|
|
|
fallthrough
|
|
|
|
|
case RSD_B:
|
2023-10-25 17:03:48 +08:00
|
|
|
|
codec = &RsspRsd{}
|
|
|
|
|
case SSE:
|
|
|
|
|
codec = &RsspSse{}
|
|
|
|
|
case SSR:
|
|
|
|
|
codec = &RsspSsr{}
|
|
|
|
|
default:
|
2023-11-02 09:24:11 +08:00
|
|
|
|
return nil
|
2023-10-25 17:03:48 +08:00
|
|
|
|
}
|
|
|
|
|
//
|
2023-11-02 09:24:11 +08:00
|
|
|
|
if codec.Decode(pack) == nil {
|
|
|
|
|
return codec.(Rssper)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
2023-10-25 17:03:48 +08:00
|
|
|
|
}
|
2023-11-01 17:46:24 +08:00
|
|
|
|
|
|
|
|
|
// PackToString 字节数组转换为16进制字节字符串
|
|
|
|
|
func PackToString(pack []byte) string {
|
|
|
|
|
b := &strings.Builder{}
|
|
|
|
|
first := true
|
|
|
|
|
for _, d := range pack {
|
|
|
|
|
if first {
|
|
|
|
|
b.WriteString(fmt.Sprintf("0x%0X", d))
|
|
|
|
|
first = false
|
|
|
|
|
} else {
|
|
|
|
|
b.WriteString(fmt.Sprintf(",0x%0X", d))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return b.String()
|
|
|
|
|
}
|
2023-11-02 14:37:50 +08:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|