Beispiel #1
0
// 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
}