package message import ( "encoding/binary" "fmt" "strings" ) //RSSP-1 V1.0 铁路信号安全通信协议 // RsspHead rssp报文头 type RsspHead struct { //报文头-协议交互类别(1Byte) Pic byte //报文头-报文类别(1Byte) Mc byte //报文头-源地址(2Byte) Sa uint16 //报文头-目地址(2Byte) Da uint16 } func (h *RsspHead) Parse(buf []byte) bool { if len(buf) < 6 { return false } h.decode(buf) return true } 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 } ///////////////////////////////////////////////// // 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 } ///////////////////////////////////////////////// // 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) ) // RsspHeadMcCheck 报文类型检测 func RsspHeadMcCheck(head *RsspHead) bool { switch head.Mc { case RSD_A | RSD_B | SSE | SSR: 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 { case PIC_MASTER | PIC_SLAVE: return true default: return false } } // 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 } // 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() }