2019-09-02 11:42:45 +01:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-09-02 17:06:21 +01:00
|
|
|
"sort"
|
2019-09-02 11:42:45 +01:00
|
|
|
|
|
|
|
"github.com/micro/go-micro/errors"
|
|
|
|
"github.com/micro/go-micro/network"
|
|
|
|
pbNet "github.com/micro/go-micro/network/proto"
|
|
|
|
pbRtr "github.com/micro/go-micro/router/proto"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Network implements network handler
|
|
|
|
type Network struct {
|
|
|
|
Network network.Network
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListRoutes returns a list of routing table routes
|
|
|
|
func (n *Network) ListRoutes(ctx context.Context, req *pbRtr.Request, resp *pbRtr.ListResponse) error {
|
|
|
|
routes, err := n.Network.Options().Router.Table().List()
|
|
|
|
if err != nil {
|
|
|
|
return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var respRoutes []*pbRtr.Route
|
|
|
|
for _, route := range routes {
|
|
|
|
respRoute := &pbRtr.Route{
|
|
|
|
Service: route.Service,
|
|
|
|
Address: route.Address,
|
|
|
|
Gateway: route.Gateway,
|
|
|
|
Network: route.Network,
|
|
|
|
Router: route.Router,
|
|
|
|
Link: route.Link,
|
|
|
|
Metric: int64(route.Metric),
|
|
|
|
}
|
|
|
|
respRoutes = append(respRoutes, respRoute)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp.Routes = respRoutes
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListNodes returns a list of all accessible nodes in the network
|
|
|
|
func (n *Network) ListNodes(ctx context.Context, req *pbNet.ListRequest, resp *pbNet.ListResponse) error {
|
2019-09-02 17:06:21 +01:00
|
|
|
nodes := n.Network.Nodes()
|
|
|
|
|
|
|
|
var respNodes []*pbNet.Node
|
|
|
|
for _, node := range nodes {
|
|
|
|
respNode := &pbNet.Node{
|
|
|
|
Id: node.Id(),
|
|
|
|
Address: node.Address(),
|
|
|
|
}
|
|
|
|
respNodes = append(respNodes, respNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp.Nodes = respNodes
|
|
|
|
|
2019-09-02 11:42:45 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-09-02 17:06:21 +01:00
|
|
|
// Neighbourhood returns a list of immediate neighbours
|
|
|
|
func (n *Network) Neighbourhood(ctx context.Context, req *pbNet.NeighbourhoodRequest, resp *pbNet.NeighbourhoodResponse) error {
|
|
|
|
// extract the id of the node to query
|
|
|
|
id := req.Id
|
|
|
|
// if no id is passed, we assume local node
|
|
|
|
if id == "" {
|
|
|
|
id = n.Network.Id()
|
|
|
|
}
|
|
|
|
|
|
|
|
// get all the nodes in the network
|
|
|
|
nodes := n.Network.Nodes()
|
|
|
|
|
2019-09-02 20:00:52 +01:00
|
|
|
// sort the slice of nodes
|
|
|
|
sort.Slice(nodes, func(i, j int) bool { return nodes[i].Id() <= nodes[j].Id() })
|
2019-09-02 17:06:21 +01:00
|
|
|
// find a node with a given id
|
2019-09-02 20:00:52 +01:00
|
|
|
i := sort.Search(len(nodes), func(j int) bool { return nodes[j].Id() >= id })
|
|
|
|
|
2019-09-03 16:39:27 +01:00
|
|
|
var neighbours []*pbNet.Node
|
2019-09-02 17:06:21 +01:00
|
|
|
// collect all the nodes in the neighbourhood of the found node
|
|
|
|
if i < len(nodes) && nodes[i].Id() == id {
|
|
|
|
for _, neighbour := range nodes[i].Neighbourhood() {
|
2019-09-03 16:39:27 +01:00
|
|
|
// don't return yourself in response
|
|
|
|
if neighbour.Id() == n.Network.Id() {
|
|
|
|
continue
|
2019-09-02 17:06:21 +01:00
|
|
|
}
|
2019-09-03 16:39:27 +01:00
|
|
|
pbNeighbour := &pbNet.Node{
|
|
|
|
Id: neighbour.Id(),
|
|
|
|
Address: neighbour.Address(),
|
2019-09-02 17:06:21 +01:00
|
|
|
}
|
2019-09-03 16:39:27 +01:00
|
|
|
neighbours = append(neighbours, pbNeighbour)
|
2019-09-02 17:06:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-03 16:39:27 +01:00
|
|
|
// requested neighbourhood node
|
|
|
|
node := &pbNet.Node{
|
|
|
|
Id: nodes[i].Id(),
|
|
|
|
Address: nodes[i].Address(),
|
|
|
|
}
|
|
|
|
|
|
|
|
// creaate neighbourhood answer
|
|
|
|
neighbourhood := &pbNet.Neighbour{
|
|
|
|
Node: node,
|
|
|
|
Neighbours: neighbours,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp.Neighbourhood = neighbourhood
|
2019-09-02 17:06:21 +01:00
|
|
|
|
2019-09-02 11:42:45 +01:00
|
|
|
return nil
|
|
|
|
}
|