261 lines
6.4 KiB
Go
261 lines
6.4 KiB
Go
package message
|
||
|
||
import (
|
||
"encoding/binary"
|
||
"fmt"
|
||
)
|
||
|
||
//RSSP-1 V1.0 铁路信号安全通信协议
|
||
|
||
// RsspHead rssp报文头
|
||
type RsspHead struct {
|
||
//报文头-协议交互类别(1Byte)
|
||
Pic byte
|
||
//报文头-报文类别(1Byte)
|
||
Mc byte
|
||
//报文头-源地址(2Byte)
|
||
Sa uint16
|
||
//报文头-目地址(2Byte)
|
||
Da uint16
|
||
}
|
||
|
||
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
|
||
}
|
||
|
||
/////////////////////////////////////////////////
|
||
|
||
// RsspRsd 实时安全数据包
|
||
type RsspRsd struct {
|
||
RsspHead
|
||
//安全校验域-序列号(4Byte)
|
||
Sn uint32
|
||
//安全校验域-安全数据长度(2Byte)
|
||
Sdl uint16
|
||
//安全校验域-安全校验通道1(4Byte)
|
||
Svc1 uint32
|
||
//安全校验域-安全校验通道2(4Byte)
|
||
Svc2 uint32
|
||
//用户数据包-安全应用数据(总字节数480)
|
||
Sad []byte
|
||
//报文尾-CRC16(2Byte)
|
||
Crc16 uint16
|
||
}
|
||
|
||
const (
|
||
CRC32_G_C1 = (uint64(0x01) << 32) | uint64(0x100d4e63) //crc32生成多项式
|
||
CRC32_G_C2 = (uint64(0x01) << 32) | uint64(0x8ce56011) //crc32生成多项式
|
||
SCW_C1 = uint32(0xae390b5a) //SCW常
|
||
SCW_C2 = uint32(0xc103589c) //SCW常
|
||
SJC_C1 = uint32(0x0fc22f87) //时间戳生成多项式
|
||
SJC_C2 = uint32(0xc3e887e1) //时间戳生成多项式
|
||
)
|
||
|
||
func (r *RsspRsd) Encode() []byte {
|
||
data := make([]byte, 0, 6+14+len(r.Sad)+2)
|
||
//报文头
|
||
data = append(data, r.RsspHead.encode()...)
|
||
//安全校验域
|
||
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
|
||
r.Crc16 = RsspCrc16(data)
|
||
data = binary.LittleEndian.AppendUint16(data, r.Crc16)
|
||
//
|
||
return data
|
||
}
|
||
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])
|
||
//
|
||
return nil
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////
|
||
|
||
// RsspSse 时序校正请求包
|
||
type RsspSse struct {
|
||
RsspHead
|
||
//安全校验域-序列号(4Byte)
|
||
Sn uint32
|
||
//安全校验域-时序校正请求通道1(4Byte)
|
||
SeqEnq1 uint32
|
||
//安全校验域-时序校正请求通道2(4Byte)
|
||
SeqEnq2 uint32
|
||
//报文尾-CRC16(2Byte)
|
||
Crc16 uint16
|
||
}
|
||
|
||
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
|
||
r.Crc16 = RsspCrc16(data)
|
||
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
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////
|
||
|
||
// 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
|
||
}
|
||
|
||
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
|
||
r.Crc16 = RsspCrc16(data)
|
||
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
|
||
|
||
const (
|
||
RSD_A = RsspType(0x80)
|
||
RSD_B = RsspType(0x81)
|
||
SSE = RsspType(0x90)
|
||
SSR = RsspType(0x91)
|
||
)
|
||
|
||
// ParseRsspPack 解析RSSP数据包
|
||
func ParseRsspPack(pack []byte) (Rssper, error) {
|
||
// pack 进行CRC16循环冗余校验,检测整个包的完整性
|
||
gCrc16 := RsspCrc16(pack[0 : len(pack)-2])
|
||
pCrc16 := binary.LittleEndian.Uint16(pack[len(pack)-2 : len(pack)])
|
||
if gCrc16 != pCrc16 {
|
||
return nil, fmt.Errorf("ParseRsspPack 整个数据包CRC16校验未通过")
|
||
}
|
||
//
|
||
ph := &RsspHead{}
|
||
ph.decode(pack)
|
||
//
|
||
var codec RsspCodec
|
||
switch ph.Mc {
|
||
case RSD_A | RSD_B:
|
||
codec = &RsspRsd{}
|
||
case SSE:
|
||
codec = &RsspSse{}
|
||
case SSR:
|
||
codec = &RsspSsr{}
|
||
default:
|
||
return nil, fmt.Errorf("ParseRsspPack 无法识别的报文类型码[0x%x]", ph.Mc)
|
||
}
|
||
//
|
||
e := codec.Decode(pack)
|
||
return codec.(Rssper), e
|
||
}
|