// Package hello // @Author: Pei Xinyuan // @Description: // @Version: 0.1.0 // @Date: 2022/7/14 14:49 // @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 // package hello import ( common2 "minlib/common" "minlib/component" "minlib/logicface" "minlib/packet" "minlib/security" "mlsr/common" "mlsr/lsa" "mlsr/lsdb" "mlsr/route" "mlsr/utils" ) // 用于hello兴趣包的名称的组件 const INFO_COMPONENT = "INFO" const MLSR_COMPONENT = "mlsr" // 正常收到数据包的触发函数 type DataCallback = func(interest *packet.Interest, data *packet.Data) // 收到NACK的触发函数 type NackCallback = func(interest *packet.Interest, nack *packet.Nack) // 超时未响应的触发函数 type TimeoutCallback = func(interest *packet.Interest) //type OptionalNack = *packet.Nack type HelloProtocol struct { m_face *logicface.LogicFace m_scheduler *lsdb.MlsrScheduler m_keychain *security.KeyChain mlsrConfig *common.MlsrConfig m_routingTable *route.RoutingTable m_lsdb *lsdb.Lsdb m_adjacencyList *lsa.AdjLsaAdjacenctList // 收包池 receivePacketQue chan *packet.Interest // 从其它路由器收包后,放入该队列 state bool // 程序生成状态, true 为正常运行, false 为关闭状态 // 接收到hello响应数据包后的信号量触发 OnInitialHelloDataValidated *utils.Signal } // // Init // @Description: Hello协议-初始化 // @receiver hp // @param face // @param scheduler // @param keychain // @param mlsrConfig // @param routingTable // @param mlsdb // func (hp *HelloProtocol) Init(face *logicface.LogicFace, scheduler *lsdb.MlsrScheduler, keychain *security.KeyChain, mlsrConfig *common.MlsrConfig, routingTable *route.RoutingTable, mlsdb *lsdb.Lsdb) { // 信号量初始化 hp.OnInitialHelloDataValidated = utils.NewSignal() // 其它数据结构 hp.m_face = face hp.m_scheduler = scheduler hp.m_keychain = keychain hp.mlsrConfig = mlsrConfig hp.m_routingTable = routingTable hp.m_lsdb = mlsdb hp.m_adjacencyList = mlsrConfig.GetAdjacencys() // logicface相关 // 构造接收hello兴趣包的前缀 name, err := component.CreateIdentifierByString( hp.mlsrConfig.GetRouterPrefix().ToUri() + "/" + MLSR_COMPONENT + "/" + INFO_COMPONENT) if err != nil { common2.LogFatal("HelloProtocol Setting interest filter for Hello interest error, interest generate wrong.", err) return } // 设置监听前缀 err = hp.m_face.RegisterPullIdentifier(name, 3000) if err != nil { common2.LogFatal("HelloProtocol Setting interest filter for Hello interest error, identifier register wrong.", err) return } // 开一个线程去接收前缀为hello协议所监听前缀的兴趣包,并进行处理 hp.receivePacketQue = make(chan *packet.Interest, 1000) hp.state = true // 启动处理接收到的包的协程 go hp.dealWithRecvPktRoutine() // 启动从客户端接收包的协程 go hp.recvPacketFromClientRoutine() } // // expressInterest // @Description: 根据传入的兴趣包名称和兴趣包过期时间,构建兴趣包,并发出去 // @receiver hp // @param interestName // @param _millseconds // func (hp *HelloProtocol) expressInterest(interestName *component.Identifier, _millseconds uint32) { common2.LogDebug("HelloProtocol Expressing Interest: " + interestName.ToUri()) interest := packet.NewInterest() interest.SetName(interestName) interest.SetInterestLifeTime(uint64(_millseconds)) // todo 这里需要实现的是,将兴趣包通过face发出,并对超时、nack、正常应答三种情况进行处理 } // // SendHelloInterest // @Description: 向指定邻居路由器发送hello探测包 // @receiver hp // @param neighbor // func (hp *HelloProtocol) SendHelloInterest(neighbor *component.Identifier) { // 查找关于某个邻居路由器的邻接信息 adjInfo := hp.m_adjacencyList.FindAdjacencyByRouterIdentifier(neighbor) // 如果没有找到,则不做处理 if adjInfo == nil { return } // 如果找到了,且有对应的faceID,则发送一个hello探测包 if adjInfo.LogicFaceId() != 0 { // interest name: //NLSR/INFO/ name, err := component.CreateIdentifierByString(adjInfo.GetNeighborRouterIdentifier().ToUri() + "/" + MLSR_COMPONENT + "/" + INFO_COMPONENT + "/" + GetSinglePrefixForHelloProtocol(hp.mlsrConfig.GetRouterPrefix())) if err != nil { common2.LogDebug("HelloProtocol SendHelloInterest error, hello name create wrong.", err) return } // 将data发出去 hp.expressInterest(name, hp.mlsrConfig.GetInterestResendTime()) common2.LogDebug("HelloProtocol Sending HELLO interest: " + name.ToUri()) } // 安排按照配置文件中的时间,若干秒后【默认一分钟】发送下一个hello兴趣包 job, err := hp.m_scheduler.ScheduleTaskAfterDuration(hp.mlsrConfig.GetInfoInterestInterval(), 1). Do(hp.SendHelloInterest, neighbor) job.LimitRunsTo(1) hp.m_scheduler.StartAsync() if err != nil { common2.LogError("HelloProtocol ScheduleTask to send hello interest error. ", err.Error()) } } // // processInterestTimedOut // @Description: 发送兴趣包给邻居路由器,当超时或nack时,执行本函数 // @receiver hp // @param interest // func (hp *HelloProtocol) processInterestTimedOut(interest *packet.Interest) { // interest name: //NLSR/INFO/ interestName := interest.GetName() // 取出兴趣包倒数第二个组件,对其进行校验 infoComponent, err := interestName.Get(-2) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, get(-2) err ", err) return } if infoComponent.ToUri() != INFO_COMPONENT { common2.LogDebug("HelloProtocol processInterestTimedOut error, INFO_COMPONENT not found in interestName ", err) return } // 取"/NLSR"之前的所有组件组成的前缀,也即邻居路由器的前缀 neighborIdentifier, err := interestName.GetPrefix(-3) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, interestName.GetPrefix error.", err) return } // 将本机邻居列表中该邻居的超时次数增加1 err = hp.m_adjacencyList.IncrementTimedOutInterestCount(neighborIdentifier) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, IncrementTimedOutInterestCount error.", err) return } // 查找该邻居的状态 status, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, GetStatusOfNeighbor error.", err) return } // 查找该邻居的超时次数 infoIntTimedOutCount, err := hp.m_adjacencyList.GetTimedOutInterestCount(neighborIdentifier) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, GetTimedOutInterestCount error.", err) return } common2.LogDebug("HelloProtocol processInterestTimedOut Status: ", status) common2.LogDebug("HelloProtocol processInterestTimedOut TimeoutCount: ", infoIntTimedOutCount) // 如果超时次数小于阈值。则继续探测 if infoIntTimedOutCount < hp.mlsrConfig.GetInterestResendTime() { name, err := component.CreateIdentifierByString(neighborIdentifier.ToUri() + "/" + MLSR_COMPONENT + "/" + INFO_COMPONENT + "/" + GetSinglePrefixForHelloProtocol(hp.mlsrConfig.GetRouterPrefix())) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, hello name create wrong.") return } common2.LogDebug("HelloProtocol processInterestTimedOut Resending interest: " + interestName.ToUri()) // 将兴趣包再次发出去 hp.expressInterest(name, hp.mlsrConfig.GetInterestResendTime()) } else if status == lsa.STATUS_ACTIVE { // 如果重传次数达到阈值,且该路由器旧状态为激活状态,则将其修改为未激活 err = hp.m_adjacencyList.SetStatusOfNeighbor(neighborIdentifier, lsa.STATUS_INACTIVE) if err != nil { common2.LogDebug("HelloProtocol processInterestTimedOut error, set status error. ", err) } common2.LogDebug("HelloProtocol processInterestTimedOut, change status of " + neighborIdentifier.ToUri() + " to IN-ACTIVE") // 安排lsdb的邻接lsa重新构建 hp.m_lsdb.ScheduleAdjLsaBuild() } } // // onContent // @Description: 发送兴趣包给邻居路由器,当收到data包时,执行本函数 // @receiver hp // @param data // func (hp *HelloProtocol) onContent(interest *packet.Interest, data *packet.Data) { common2.LogDebug("HelloProtocol Received data for INFO(name): " + data.GetName().ToUri()) // todo 这里先跳过签名验证,执行验证通过后的处理 // 取出数据包名称的倒数第三个组件,对其进行校验 infoComponent, err := data.GetName().Get(-3) if err != nil { common2.LogDebug("HelloProtocol onContent error, get(-3) err ", err) return } if infoComponent.ToUri() != INFO_COMPONENT { common2.LogDebug("HelloProtocol onContent error, INFO_COMPONENT not found in dataName ", err) return } // 取"/NLSR"之前的所有组件组成的前缀,也即邻居路由器的前缀 neighborIdentifier, err := data.GetName().GetPrefix(-4) if err != nil { common2.LogDebug("HelloProtocol onContent error, dataName.GetPrefix error.", err) return } // 查找该邻居的状态 oldStatus, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier) if err != nil { common2.LogDebug("HelloProtocol onContent error, get old status error.", err) return } // 设置该路由器的状态及超时次数 err = hp.m_adjacencyList.SetStatusOfNeighbor(neighborIdentifier, lsa.STATUS_ACTIVE) if err != nil { common2.LogDebug("HelloProtocol onContent error, set status error.", err) return } err = hp.m_adjacencyList.SetTimedOutInterestCount(neighborIdentifier, 0) if err != nil { common2.LogDebug("HelloProtocol onContent error, set timeout count error.", err) return } // 查找该邻居的新状态 newStatus, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier) if err != nil { common2.LogDebug("HelloProtocol onContent error, get new status error.", err) return } common2.LogDebug("HelloProtocol onContent, neighbor: ", neighborIdentifier.ToUri(), ", old status: ", oldStatus, ", new status: ", newStatus) // 如果状态发生了更改,则安排邻接Lsa进行重新构建,并发射信号给fib,使其更新mir中的该face状态 if newStatus != oldStatus { hp.m_lsdb.ScheduleAdjLsaBuild() hp.OnInitialHelloDataValidated.Emit(neighborIdentifier) } }