// Rcv handles both Discovery and Advertisement messages. func (r Router) Rcv(msg bh.Msg, ctx bh.RcvContext) error { switch d := msg.Data().(type) { case Discovery: if err := r.appendNieghbor(Edge(d), ctx); err != nil { return err } if Edge(d).To.Endhost { adv, err := Path{}.Append(Edge(d).From, Edge(d).To) if err != nil { return err } ctx.Emit(Advertisement(adv)) } // Indication of an update. ctx.SetBeeLocal(true) case Advertisement: path := Path(d) if to, err := path.To(); err != nil || !to.Endhost { return errors.New("Route is not towards an end-host") } if _, err := r.appendToRoutingTable(path, ctx); err != nil { return err } case Timeout: if !ctx.BeeLocal().(bool) { return nil } ctx.SetBeeLocal(false) type keyTable struct { k string t RoutingTable } var entries []keyTable ctx.Dict(routeDict).ForEach(func(k string, v interface{}) bool { tbl := v.(RoutingTable) from := Node{ ID: string(k), } for to, route := range tbl { if len(route.Updates) == 0 { continue } shortestPaths := route.ShortestPaths() glog.V(1).Infof("Shortest paths: %v", shortestPaths) for _, p := range route.Updates { if !route.IsShortestPath(p) { continue } for _, n := range r.neighbors(from, ctx) { if np, err := p.Prepend(n.From); err == nil { ctx.Emit(Advertisement(np)) } } } route.Updates = nil tbl[to] = route } entries = append(entries, keyTable{k, tbl}) return true }) for _, e := range entries { ctx.Dict(routeDict).Put(e.k, e.t) } } return nil }