2023-11-01 17:46:24 +08:00
|
|
|
|
package axle_device
|
|
|
|
|
|
2023-11-03 13:04:28 +08:00
|
|
|
|
import (
|
2023-11-06 18:10:15 +08:00
|
|
|
|
"fmt"
|
2024-01-22 13:10:10 +08:00
|
|
|
|
"log/slog"
|
|
|
|
|
|
2023-11-09 13:05:29 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/config"
|
2023-11-03 13:04:28 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/third_party/message"
|
2023-11-06 18:10:15 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
2023-11-03 13:04:28 +08:00
|
|
|
|
)
|
2023-11-01 17:46:24 +08:00
|
|
|
|
|
2023-11-06 18:10:15 +08:00
|
|
|
|
// 铁路信号安全通信协议实现
|
|
|
|
|
|
|
|
|
|
// HandleUserData 回调应用层
|
|
|
|
|
type HandleUserData func([]byte)
|
|
|
|
|
|
2023-11-02 18:04:37 +08:00
|
|
|
|
// RsspChannel 实现rssp通信
|
|
|
|
|
type RsspChannel struct {
|
2023-11-06 18:10:15 +08:00
|
|
|
|
//udp
|
|
|
|
|
udpServer udp.UdpServer
|
|
|
|
|
//udp
|
|
|
|
|
udpClient udp.UdpClient
|
|
|
|
|
//回调应用层
|
|
|
|
|
handleUserData HandleUserData
|
2023-11-03 17:12:52 +08:00
|
|
|
|
//rssp安全通信配置
|
2023-11-09 13:05:29 +08:00
|
|
|
|
config *config.RsspConfig
|
2023-11-03 17:12:52 +08:00
|
|
|
|
//rssp时钟
|
|
|
|
|
rsspTimer *RsspTimer
|
|
|
|
|
//批次编号,发送序列号
|
2023-11-02 18:04:37 +08:00
|
|
|
|
sn *message.RsspSn
|
|
|
|
|
//安全通道1时间戳
|
|
|
|
|
ch1Ts *message.RsspLFSR
|
|
|
|
|
//安全通道2时间戳
|
|
|
|
|
ch2Ts *message.RsspLFSR
|
|
|
|
|
//最近一次接收到的报文的安全通道1时间戳
|
|
|
|
|
rcvCh1Ts uint32
|
|
|
|
|
//最近一次接收到的报文的安全通道2时间戳
|
|
|
|
|
rcvCh2Ts uint32
|
|
|
|
|
//最近一次接收到的报文的序列号
|
|
|
|
|
rcvSn uint32
|
2023-11-03 17:12:52 +08:00
|
|
|
|
//时序校验请求发送记录
|
|
|
|
|
sendSseRecord *SseFireRecord
|
2023-11-02 09:24:11 +08:00
|
|
|
|
}
|
2023-11-01 17:46:24 +08:00
|
|
|
|
|
2023-11-14 17:57:54 +08:00
|
|
|
|
func (s *RsspChannel) SetRcvUserDataCallback(handleUserData HandleUserData) {
|
|
|
|
|
s.handleUserData = handleUserData
|
|
|
|
|
}
|
2023-11-09 13:05:29 +08:00
|
|
|
|
func (s *RsspChannel) Init(config *config.RsspConfig) *RsspChannel {
|
2023-11-06 18:10:15 +08:00
|
|
|
|
s.config = config
|
2023-11-07 13:22:47 +08:00
|
|
|
|
s.rsspTimer = &RsspTimer{t: 0}
|
|
|
|
|
s.sn = message.NewRsspSn(1)
|
2024-01-22 13:10:10 +08:00
|
|
|
|
s.ch1Ts = message.NewRsspLFSR(message.RSSP_I_C1_TS, 32, s.config.SID1, false)
|
|
|
|
|
s.ch2Ts = message.NewRsspLFSR(message.RSSP_I_C2_TS, 32, s.config.SID2, false)
|
2023-11-09 13:05:29 +08:00
|
|
|
|
return s
|
2023-11-06 18:10:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start 启动安全通道
|
|
|
|
|
func (s *RsspChannel) Start() {
|
|
|
|
|
//
|
|
|
|
|
s.udpServer = udp.NewServer(fmt.Sprintf(":%d", s.config.LocalUdpPort), s.handleRsspMsg)
|
|
|
|
|
s.udpServer.Listen()
|
|
|
|
|
//
|
|
|
|
|
s.udpClient = udp.NewClient(fmt.Sprintf("%s:%d", s.config.RemoteIp, s.config.RemoteUdpPort))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop 关闭安全通道
|
|
|
|
|
func (s *RsspChannel) Stop() {
|
|
|
|
|
if s.udpServer != nil {
|
|
|
|
|
s.udpServer.Close()
|
|
|
|
|
}
|
|
|
|
|
if s.udpClient != nil {
|
|
|
|
|
s.udpClient.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 17:12:52 +08:00
|
|
|
|
// RsspTimer rssp时钟,每一个tick周期为config.SendingPeriod
|
|
|
|
|
type RsspTimer struct {
|
|
|
|
|
t uint64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *RsspTimer) tick() {
|
|
|
|
|
s.t++
|
|
|
|
|
}
|
|
|
|
|
func (s *RsspTimer) now() uint64 {
|
|
|
|
|
return s.t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SseFireRecord 发送时序校验请求的记录
|
|
|
|
|
type SseFireRecord struct {
|
|
|
|
|
send *message.RsspSse //已经发送的时序校验请求
|
|
|
|
|
rsspTime uint64 //发送时序校验请求时的rssp时间
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *SseFireRecord) record(send *message.RsspSse, rsspTime uint64) {
|
|
|
|
|
s.send = send
|
|
|
|
|
s.rsspTime = rsspTime
|
|
|
|
|
}
|
|
|
|
|
func (s *SseFireRecord) clear() {
|
|
|
|
|
s.send = nil
|
|
|
|
|
s.rsspTime = 0
|
|
|
|
|
}
|
|
|
|
|
func (s *SseFireRecord) hasRecord() bool {
|
|
|
|
|
return s.send != nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理接收到的rssp报文
|
2023-11-06 18:10:15 +08:00
|
|
|
|
// 注意本函数由udp socket 协程执行
|
2023-11-03 17:12:52 +08:00
|
|
|
|
func (s *RsspChannel) handleRsspMsg(pack []byte) {
|
2023-11-14 17:57:54 +08:00
|
|
|
|
slog.Debug("接收到RSSP报文", "len", len(pack))
|
2023-11-01 17:46:24 +08:00
|
|
|
|
//报文头校验
|
|
|
|
|
head := &message.RsspHead{}
|
|
|
|
|
if !head.Parse(pack) { //解析报文头失败
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:解析报文头失败")
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if !message.RsspHeadMcCheck(head) { //报文类别检测未通过
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:报文类别检测未通过")
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if !message.RsspHeadPicCheck(head) { //协议交互类别检测未通过
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:协议交互类别检测未通过")
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-02 18:04:37 +08:00
|
|
|
|
if !s.config.CheckAddress(head.Sa, head.Da) { //校验报文头中源地址和目的地址是否包含在已配置列表中
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:报文头中源地址或目的地址不在在已配置列表中")
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
//报文尾校验
|
|
|
|
|
if !message.RsspPackCrc16Check(pack) { //整个报文crc16校验未通过
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:报文尾CRC16校验未通过")
|
2023-11-01 17:46:24 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-02 09:24:11 +08:00
|
|
|
|
//解析得到RSD、SSE或SRE
|
|
|
|
|
rssp := message.ParseRsspPack(head, pack)
|
|
|
|
|
if rssp == nil { //解析具体rssp包失败
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP报文:解析具体类别包失败")
|
2023-11-02 09:24:11 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-03 13:04:28 +08:00
|
|
|
|
//处理接收到的具体类别RSSP包
|
2023-11-02 09:24:11 +08:00
|
|
|
|
switch rssp.Type() {
|
|
|
|
|
case message.RSD_A:
|
|
|
|
|
fallthrough
|
|
|
|
|
case message.RSD_B:
|
2023-11-03 13:04:28 +08:00
|
|
|
|
s.handleRsspRsd(rssp.(*message.RsspRsd))
|
2023-11-02 09:24:11 +08:00
|
|
|
|
case message.SSE:
|
2023-11-03 13:04:28 +08:00
|
|
|
|
s.handleRsspSse(rssp.(*message.RsspSse))
|
2023-11-02 09:24:11 +08:00
|
|
|
|
case message.SSR:
|
2023-11-03 13:04:28 +08:00
|
|
|
|
s.handleRsspSsr(rssp.(*message.RsspSsr))
|
2023-11-02 09:24:11 +08:00
|
|
|
|
}
|
2023-11-01 17:46:24 +08:00
|
|
|
|
}
|
2023-11-02 18:04:37 +08:00
|
|
|
|
|
2023-11-13 17:35:53 +08:00
|
|
|
|
// 处理接收到的实时安全数据 RSD
|
2023-11-03 13:04:28 +08:00
|
|
|
|
func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) {
|
2023-11-14 17:57:54 +08:00
|
|
|
|
//slog.Debug("接收到的实时安全数据 RSD")
|
2023-11-13 17:35:53 +08:00
|
|
|
|
//如果为备机发送来的安全数据
|
|
|
|
|
if s.config.PicType == message.PIC_SLAVE { //备安全通道
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-RSD报文:舍弃在备安全通道中接收到的安全数据")
|
|
|
|
|
//备安全通道收到安全数据,表示该物理通道连接正常
|
2023-11-03 17:12:52 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-13 17:35:53 +08:00
|
|
|
|
//如果为主机发送来的安全数据
|
|
|
|
|
if s.config.PicType == message.PIC_MASTER { //主安全通道
|
|
|
|
|
if !rsd.IsMaster() {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-RSD报文:舍弃在主安全通道中收到的非主机发送来的安全数据")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-03 13:04:28 +08:00
|
|
|
|
//序列号校验
|
|
|
|
|
//接收的序列号小于最近一次有效序列号,则触发SSE时序校验
|
|
|
|
|
if rsd.Sn < s.rcvSn {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-RSD报文:当前接收RSD的序列号小于最近一次接收的RSD的序列号,触发SSE")
|
|
|
|
|
s.fireSse(rsd)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-03 17:12:52 +08:00
|
|
|
|
dSn := rsd.Sn - s.rcvSn
|
|
|
|
|
if dSn > s.config.Mtv {
|
2023-11-03 13:04:28 +08:00
|
|
|
|
slog.Debug("丢弃接收的RSSP-RSD报文:当前接收RSD的序列号与最近一次接收的RSD的序列号差值过大,触发SSE")
|
|
|
|
|
s.fireSse(rsd)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
//SVC校验
|
2024-01-22 13:10:10 +08:00
|
|
|
|
c1Crc32 := message.Rssp_I_Crc32C1(rsd.Sad)
|
|
|
|
|
c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.RSSP_I_C1_SCW //T(n)
|
2023-11-03 17:12:52 +08:00
|
|
|
|
//
|
2024-01-22 13:10:10 +08:00
|
|
|
|
c2Crc32 := message.Rssp_I_Crc32C2(rsd.Sad)
|
|
|
|
|
c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.RSSP_I_C2_SCW //T(n)
|
2023-11-03 17:12:52 +08:00
|
|
|
|
//todo ... SVC校验待完善
|
|
|
|
|
_ = c1SidTs
|
|
|
|
|
_ = c2SidTs
|
|
|
|
|
//校验通过
|
|
|
|
|
//记录本次接收RSD的序列号和安全校验通道时间戳
|
|
|
|
|
s.rcvSn = rsd.Sn
|
|
|
|
|
s.rcvCh1Ts = c1SidTs ^ s.config.SID1
|
|
|
|
|
s.rcvCh2Ts = c2SidTs ^ s.config.SID2
|
|
|
|
|
//通知应用层接收应用数据
|
2023-11-06 18:10:15 +08:00
|
|
|
|
s.handleUserData(rsd.Sad)
|
2023-11-03 13:04:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 触发时序校正请求
|
|
|
|
|
func (s *RsspChannel) fireSse(rsd *message.RsspRsd) {
|
2023-11-13 17:35:53 +08:00
|
|
|
|
s.sendSseRecord = &SseFireRecord{send: s.sendSse(), rsspTime: s.rsspTimer.now()}
|
2023-11-03 13:04:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 接收到时序校正请求
|
2023-11-13 17:35:53 +08:00
|
|
|
|
func (s *RsspChannel) handleRsspSse(sse *message.RsspSse) {
|
|
|
|
|
if s.config.PicType != message.PIC_MASTER {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-SSE报文:在非主安全通道中收到时序校正请求SSE")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
//发送时序校正响应
|
|
|
|
|
s.sendSsr(sse)
|
2023-11-03 13:04:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 接收到时序校正应答
|
2023-11-03 17:12:52 +08:00
|
|
|
|
func (s *RsspChannel) handleRsspSsr(ssr *message.RsspSsr) {
|
|
|
|
|
//SSR校验
|
|
|
|
|
if !s.sendSseRecord.hasRecord() {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-SSR报文:未发起过SSE时序校正请求")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if s.rsspTimer.t-s.sendSseRecord.rsspTime > uint64(s.config.SsrRsspTimeout) {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-SSR报文:等待SSE响应超时")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if ssr.SeSn != s.sendSseRecord.send.Sn {
|
|
|
|
|
slog.Debug("丢弃接收的RSSP-SSR报文:SSR与SSE不对应")
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-14 17:57:54 +08:00
|
|
|
|
//恢复时序?
|
|
|
|
|
s.rcvSn = ssr.SrSn
|
|
|
|
|
s.rcvCh1Ts = ssr.Tic1 ^ s.sendSseRecord.send.SeqEnq1 ^ s.config.SID1 ^ s.config.DataVer1
|
|
|
|
|
s.rcvCh2Ts = ssr.Tic2 ^ s.sendSseRecord.send.SeqEnq2 ^ s.config.SID2 ^ s.config.DataVer2
|
2023-11-03 13:04:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-14 17:57:54 +08:00
|
|
|
|
// NextPeriod 刷新与周期有关的:将序列号和时间戳更新到下一个值
|
|
|
|
|
func (s *RsspChannel) NextPeriod() {
|
2023-11-02 18:04:37 +08:00
|
|
|
|
s.sn.GetAndAdd()
|
|
|
|
|
s.ch1Ts.GetAndMove()
|
|
|
|
|
s.ch2Ts.GetAndMove()
|
2023-11-13 17:35:53 +08:00
|
|
|
|
s.rsspTimer.tick()
|
2023-11-02 18:04:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送时序校正应答
|
|
|
|
|
func (s *RsspChannel) sendSsr(sse *message.RsspSse) {
|
|
|
|
|
ssr := &message.RsspSsr{}
|
|
|
|
|
//
|
|
|
|
|
ssr.Pic = message.PIC_MASTER
|
|
|
|
|
ssr.Mc = message.SSR
|
|
|
|
|
ssr.Sa = s.config.SrcAddr
|
|
|
|
|
ssr.Da = s.config.DstAddr
|
|
|
|
|
ssr.SrSn = s.sn.Get() //当前序列号
|
|
|
|
|
ssr.SeSn = sse.Sn
|
|
|
|
|
ssr.Tic1 = sse.SeqEnq1 ^ s.config.SID1 ^ s.ch1Ts.Get() ^ s.config.DataVer1
|
|
|
|
|
ssr.Tic2 = sse.SeqEnq2 ^ s.config.SID2 ^ s.ch2Ts.Get() ^ s.config.DataVer2
|
|
|
|
|
ssr.Dvn = 0x01 //预留固定值
|
|
|
|
|
//
|
|
|
|
|
rsspPack := ssr.Encode()
|
|
|
|
|
s.sendPack(rsspPack)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送时序校正请求
|
2023-11-13 17:35:53 +08:00
|
|
|
|
func (s *RsspChannel) sendSse() *message.RsspSse {
|
2023-11-02 18:04:37 +08:00
|
|
|
|
sse := &message.RsspSse{}
|
|
|
|
|
//
|
|
|
|
|
sse.Pic = message.PIC_MASTER
|
|
|
|
|
sse.Mc = message.SSE
|
|
|
|
|
sse.Sa = s.config.SrcAddr
|
|
|
|
|
sse.Da = s.config.DstAddr
|
|
|
|
|
//时序校正请求,把最近一次接收到的报文中的序列号时间戳发送给发送方
|
|
|
|
|
sse.Sn = s.rcvSn
|
|
|
|
|
sse.SeqEnq1 = s.createSeqNeq(s.config.SID1, s.rcvCh1Ts)
|
|
|
|
|
sse.SeqEnq2 = s.createSeqNeq(s.config.SID2, s.rcvCh2Ts)
|
|
|
|
|
//
|
|
|
|
|
rsspPack := sse.Encode()
|
|
|
|
|
s.sendPack(rsspPack)
|
2023-11-13 17:35:53 +08:00
|
|
|
|
//
|
|
|
|
|
return sse
|
2023-11-02 18:04:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-14 17:57:54 +08:00
|
|
|
|
// SendUserData 发送用户数据,即通过rssp安全通道发送应用层数据,通过rssp的RSD报文发送
|
|
|
|
|
func (s *RsspChannel) SendUserData(userData []byte) {
|
2023-11-02 18:04:37 +08:00
|
|
|
|
rsd := &message.RsspRsd{}
|
2023-11-06 18:10:15 +08:00
|
|
|
|
rsd.Pic = s.config.PicType
|
|
|
|
|
if s.config.DeviceA {
|
2023-11-02 18:04:37 +08:00
|
|
|
|
rsd.Mc = message.RSD_A
|
|
|
|
|
} else {
|
|
|
|
|
rsd.Mc = message.RSD_B
|
|
|
|
|
}
|
|
|
|
|
rsd.Sa = s.config.SrcAddr
|
|
|
|
|
rsd.Da = s.config.DstAddr
|
|
|
|
|
//
|
|
|
|
|
rsd.Sn = s.sn.Get()
|
|
|
|
|
rsd.Sdl = uint16(len(userData) + 8)
|
|
|
|
|
//安全校验通道SVC_1
|
2024-01-22 13:10:10 +08:00
|
|
|
|
crc_c1 := message.Rssp_I_Crc32C1(userData)
|
|
|
|
|
rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.RSSP_I_C1_SCW)
|
2023-11-02 18:04:37 +08:00
|
|
|
|
//安全校验通道SVC_2
|
2024-01-22 13:10:10 +08:00
|
|
|
|
crc_c2 := message.Rssp_I_Crc32C2(userData)
|
|
|
|
|
rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.RSSP_I_C2_SCW)
|
2023-11-02 18:04:37 +08:00
|
|
|
|
rsd.Sad = userData
|
|
|
|
|
//
|
|
|
|
|
rsspPack := rsd.Encode()
|
|
|
|
|
s.sendPack(rsspPack)
|
|
|
|
|
}
|
|
|
|
|
func (s *RsspChannel) createSvcCode(crc32 uint32, sid uint32, ts uint32, scw uint32) uint32 {
|
|
|
|
|
return crc32 ^ sid ^ ts ^ scw
|
|
|
|
|
}
|
|
|
|
|
func (s *RsspChannel) createSeqNeq(sid uint32, ts uint32) uint32 {
|
|
|
|
|
return sid ^ ts
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通过网络发送数据
|
|
|
|
|
func (s *RsspChannel) sendPack(rsspPack []byte) {
|
2023-11-06 18:10:15 +08:00
|
|
|
|
s.udpClient.Send(rsspPack)
|
2023-11-02 18:04:37 +08:00
|
|
|
|
}
|