diff --git a/network/handler/handler.go b/network/handler/handler.go index 89c63cef..e09802f3 100644 --- a/network/handler/handler.go +++ b/network/handler/handler.go @@ -3,7 +3,6 @@ package handler import ( "context" - "sort" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/network" @@ -18,65 +17,33 @@ type Network struct { // 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 { - nodes := n.Network.Nodes() + networkNodes := n.Network.Nodes() - var respNodes []*pbNet.Node - for _, node := range nodes { - respNode := &pbNet.Node{ - Id: node.Id(), - Address: node.Address(), + var nodes []*pbNet.Node + for _, networkNode := range networkNodes { + node := &pbNet.Node{ + Id: networkNode.Id(), + Address: networkNode.Address(), } - respNodes = append(respNodes, respNode) + nodes = append(nodes, node) } - resp.Nodes = respNodes + resp.Nodes = nodes return nil } // ListPeers returns a list of all the nodes the node has a direct link with func (n *Network) ListPeers(ctx context.Context, req *pbNet.PeerRequest, resp *pbNet.PeerResponse) 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() - } + nodePeers := n.Network.Peers() - // get all the nodes in the network - nodes := n.Network.Nodes() - - // sort the slice of nodes - sort.Slice(nodes, func(i, j int) bool { return nodes[i].Id() <= nodes[j].Id() }) - // find a node with a given id - i := sort.Search(len(nodes), func(j int) bool { return nodes[j].Id() >= id }) - - var nodePeers []*pbNet.Node - // collect all the node peers into slice - if i < len(nodes) && nodes[i].Id() == id { - for _, peer := range nodes[i].Peers() { - // don't return yourself in response - if peer.Id() == n.Network.Id() { - continue - } - pbPeer := &pbNet.Node{ - Id: peer.Id(), - Address: peer.Address(), - } - nodePeers = append(nodePeers, pbPeer) + var peers []*pbNet.Node + for _, nodePeer := range nodePeers { + peer := &pbNet.Node{ + Id: nodePeer.Id(), + Address: nodePeer.Address(), } - } - - // requested node - node := &pbNet.Node{ - Id: nodes[i].Id(), - Address: nodes[i].Address(), - } - - // creaate peers answer - peers := &pbNet.Peers{ - Node: node, - Peers: nodePeers, + peers = append(peers, peer) } resp.Peers = peers @@ -84,6 +51,43 @@ func (n *Network) ListPeers(ctx context.Context, req *pbNet.PeerRequest, resp *p return nil } +// Topology returns a list of nodes in node topology i.e. it returns all (in)directly reachable nodes from this node +func (n *Network) Topology(ctx context.Context, req *pbNet.TopologyRequest, resp *pbNet.TopologyResponse) error { + // NOTE: we are downcasting here + depth := uint(req.Depth) + if depth <= 0 { + depth = network.MaxDepth + } + + // get topology + topNodes := n.Network.Topology(depth) + + var nodes []*pbNet.Node + for _, topNode := range topNodes { + // creaate peers answer + pbNode := &pbNet.Node{ + Id: topNode.Id(), + Address: topNode.Address(), + } + nodes = append(nodes, pbNode) + } + + // network node + node := &pbNet.Node{ + Id: n.Network.Id(), + Address: n.Network.Address(), + } + + topology := &pbNet.Topology{ + Node: node, + Nodes: nodes, + } + + resp.Topology = topology + + return nil +} + // 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() diff --git a/network/network.go b/network/network.go index b500e2bc..add29576 100644 --- a/network/network.go +++ b/network/network.go @@ -46,6 +46,8 @@ type Network interface { Connect() error // Nodes returns list of network nodes Nodes() []Node + // Topology returns a list of all reachable nodes up to depth + Topology(depth uint) []Node // Close stops the tunnel and resolving Close() error // Client is micro client diff --git a/network/node.go b/network/node.go index a0381ba3..dfacdd13 100644 --- a/network/node.go +++ b/network/node.go @@ -3,15 +3,16 @@ package network import ( "container/list" "errors" + "sort" "sync" "time" - pbNet "github.com/micro/go-micro/network/proto" + pb "github.com/micro/go-micro/network/proto" ) var ( // MaxDepth defines max depth of peer topology - MaxDepth = 3 + MaxDepth uint = 3 ) // node is network node @@ -98,6 +99,7 @@ func (n *node) Peers() []Node { network: peer.network, } // NOTE: we do not care about peer's peers + // we only collect the node's peers i.e. its adjacent nodes peers = append(peers, p) } n.RUnlock() @@ -105,17 +107,49 @@ func (n *node) Peers() []Node { return peers } +// Topology returns a slice of all nodes in reachable by node up to given depth +func (n *node) Topology(depth uint) []Node { + // get all the nodes + nodes := n.Nodes() + + n.RLock() + // sort the slice of nodes + sort.Slice(nodes, func(i, j int) bool { return nodes[i].Id() <= nodes[j].Id() }) + // find the node with our id + i := sort.Search(len(nodes), func(j int) bool { return nodes[j].Id() >= n.id }) + + // TODO: finish implementing this + var topology []Node + // collect all the reachable nodes into slice + if i < len(nodes) && nodes[i].Id() == n.id { + for _, peer := range nodes[i].Peers() { + // don't return yourself + if peer.Id() == n.id { + continue + } + topNode := &node{ + id: peer.Id(), + address: peer.Address(), + } + topology = append(topology, topNode) + } + } + n.RUnlock() + + return topology +} + // getProtoTopology returns node peers up to given depth encoded in protobufs // NOTE: this method is NOT thread-safe, so make sure you serialize access to it -func (n *node) getProtoTopology(depth int) (*pbNet.Peer, error) { - node := &pbNet.Node{ +func (n *node) getProtoTopology(depth uint) (*pb.Peer, error) { + node := &pb.Node{ Id: n.id, Address: n.address, } - pbPeers := &pbNet.Peer{ + pbPeers := &pb.Peer{ Node: node, - Peers: make([]*pbNet.Peer, 0), + Peers: make([]*pb.Peer, 0), } // return if have either reached the depth or have no more peers @@ -126,7 +160,7 @@ func (n *node) getProtoTopology(depth int) (*pbNet.Peer, error) { // decrement the depth depth-- - var peers []*pbNet.Peer + var peers []*pb.Peer for _, peer := range n.peers { // get peers of the node peers // NOTE: this is [not] a recursive call @@ -144,9 +178,9 @@ func (n *node) getProtoTopology(depth int) (*pbNet.Peer, error) { return pbPeers, nil } -// unpackPeer unpacks pbNet.Peer into node topology of given depth +// unpackPeer unpacks pb.Peer into node topology of given depth // NOTE: this method is NOT thread-safe, so make sure you serialize access to it -func unpackPeer(pbPeer *pbNet.Peer, depth int) *node { +func unpackPeer(pbPeer *pb.Peer, depth uint) *node { peerNode := &node{ id: pbPeer.Node.Id, address: pbPeer.Node.Address, @@ -174,7 +208,7 @@ func unpackPeer(pbPeer *pbNet.Peer, depth int) *node { // updatePeer updates node peer up to given depth // NOTE: this method is not thread safe, so make sure you serialize access to it -func (n *node) updatePeerTopology(pbPeer *pbNet.Peer, depth int) error { +func (n *node) updatePeerTopology(pbPeer *pb.Peer, depth uint) error { if pbPeer == nil { return errors.New("peer not initialized") } diff --git a/network/node_test.go b/network/node_test.go new file mode 100644 index 00000000..dc0add63 --- /dev/null +++ b/network/node_test.go @@ -0,0 +1,174 @@ +package network + +import "testing" + +var ( + testNodeId = "testNode" + testNodeAddress = "testAddress" + testNodeNetName = "testNetwork" + testNodePeerIds = []string{"peer1", "peer2", "peer3"} + testPeerOfPeerIds = []string{"peer11", "peer12"} +) + +func testSetup() *node { + testNode := &node{ + id: testNodeId, + address: testNodeAddress, + peers: make(map[string]*node), + network: newNetwork(Name(testNodeNetName)), + } + + // add some peers to the node + for _, id := range testNodePeerIds { + testNode.peers[id] = &node{ + id: id, + address: testNode.address + "-" + id, + peers: make(map[string]*node), + network: testNode.network, + } + } + + // add peers to peer1 + // NOTE: these are peers of peers! + for _, id := range testPeerOfPeerIds { + testNode.peers["peer1"].peers[id] = &node{ + id: id, + address: testNode.address + "-" + id, + peers: make(map[string]*node), + network: testNode.network, + } + } + + // connect peer1 with peer2 + testNode.peers["peer1"].peers["peer2"] = testNode.peers["peer2"] + // connect peer2 with peer3 + testNode.peers["peer2"].peers["peer3"] = testNode.peers["peer3"] + + return testNode +} + +func TestNodeId(t *testing.T) { + node := testSetup() + if node.Id() != testNodeId { + t.Errorf("Expected id: %s, found: %s", testNodeId, node.Id()) + } +} + +func TestNodeAddress(t *testing.T) { + node := testSetup() + if node.Address() != testNodeAddress { + t.Errorf("Expected address: %s, found: %s", testNodeAddress, node.Address()) + } +} +func TestNodeNetwork(t *testing.T) { + node := testSetup() + if node.Network().Name() != testNodeNetName { + t.Errorf("Expected network: %s, found: %s", testNodeNetName, node.Network().Name()) + } +} + +func TestNodes(t *testing.T) { + // single node + single := &node{ + id: testNodeId, + address: testNodeAddress, + peers: make(map[string]*node), + network: newNetwork(Name(testNodeNetName)), + } + // get all the nodes including yourself + nodes := single.Nodes() + nodeCount := 1 + + if len(nodes) != nodeCount { + t.Errorf("Expected to find %d nodes, found: %d", nodeCount, len(nodes)) + } + + // complicated node graph + node := testSetup() + // get all the nodes including yourself + nodes = node.Nodes() + + // compile a list of ids of all nodes in the network into map for easy indexing + nodeIds := make(map[string]bool) + // add yourself + nodeIds[node.id] = true + // add peer Ids + for _, id := range testNodePeerIds { + nodeIds[id] = true + } + // add peer1 peers i.e. peers of peer + for _, id := range testPeerOfPeerIds { + nodeIds[id] = true + } + + // we should return the correct number of nodes + if len(nodes) != len(nodeIds) { + t.Errorf("Expected %d nodes, found: %d", len(nodeIds), len(nodes)) + } + + // iterate through the list of nodes and makes sure all have been returned + for _, node := range nodes { + if _, ok := nodeIds[node.Id()]; !ok { + t.Errorf("Expected to find %s node", node.Id()) + } + } +} + +func TestPeers(t *testing.T) { + // single node + single := &node{ + id: testNodeId, + address: testNodeAddress, + peers: make(map[string]*node), + network: newNetwork(Name(testNodeNetName)), + } + // get all the nodes including yourself + peers := single.Peers() + peerCount := 0 + + if len(peers) != peerCount { + t.Errorf("Expected to find %d peers, found: %d", peerCount, len(peers)) + } + + // complicated node graph + node := testSetup() + // get all the nodes including yourself + peers = node.Peers() + + // compile a list of ids of all nodes in the network into map for easy indexing + peerIds := make(map[string]bool) + // add peer Ids + for _, id := range testNodePeerIds { + peerIds[id] = true + } + + // we should return the correct number of peers + if len(peers) != len(peerIds) { + t.Errorf("Expected %d nodes, found: %d", len(peerIds), len(peers)) + } + + // iterate through the list of peers and makes sure all have been returned + for _, peer := range peers { + if _, ok := peerIds[peer.Id()]; !ok { + t.Errorf("Expected to find %s peer", node.Id()) + } + } +} + +func TestTopology(t *testing.T) { + // single node + single := &node{ + id: testNodeId, + address: testNodeAddress, + peers: make(map[string]*node), + network: newNetwork(Name(testNodeNetName)), + } + // get all the nodes including yourself + topology := single.Topology(MaxDepth) + // you should not be in your topology + topCount := 0 + + if len(topology) != topCount { + t.Errorf("Expected to find %d nodes, found: %d", topCount, len(topology)) + } +} diff --git a/network/proto/network.micro.go b/network/proto/network.micro.go index 4b5dde73..b0f1ae6b 100644 --- a/network/proto/network.micro.go +++ b/network/proto/network.micro.go @@ -37,6 +37,7 @@ var _ server.Option type NetworkService interface { ListNodes(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) ListPeers(ctx context.Context, in *PeerRequest, opts ...client.CallOption) (*PeerResponse, error) + Topology(ctx context.Context, in *TopologyRequest, opts ...client.CallOption) (*TopologyResponse, error) ListRoutes(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.ListResponse, error) } @@ -78,6 +79,16 @@ func (c *networkService) ListPeers(ctx context.Context, in *PeerRequest, opts .. return out, nil } +func (c *networkService) Topology(ctx context.Context, in *TopologyRequest, opts ...client.CallOption) (*TopologyResponse, error) { + req := c.c.NewRequest(c.name, "Network.Topology", in) + out := new(TopologyResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *networkService) ListRoutes(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.ListResponse, error) { req := c.c.NewRequest(c.name, "Network.ListRoutes", in) out := new(proto1.ListResponse) @@ -93,6 +104,7 @@ func (c *networkService) ListRoutes(ctx context.Context, in *proto1.Request, opt type NetworkHandler interface { ListNodes(context.Context, *ListRequest, *ListResponse) error ListPeers(context.Context, *PeerRequest, *PeerResponse) error + Topology(context.Context, *TopologyRequest, *TopologyResponse) error ListRoutes(context.Context, *proto1.Request, *proto1.ListResponse) error } @@ -100,6 +112,7 @@ func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server type network interface { ListNodes(ctx context.Context, in *ListRequest, out *ListResponse) error ListPeers(ctx context.Context, in *PeerRequest, out *PeerResponse) error + Topology(ctx context.Context, in *TopologyRequest, out *TopologyResponse) error ListRoutes(ctx context.Context, in *proto1.Request, out *proto1.ListResponse) error } type Network struct { @@ -121,6 +134,10 @@ func (h *networkHandler) ListPeers(ctx context.Context, in *PeerRequest, out *Pe return h.NetworkHandler.ListPeers(ctx, in, out) } +func (h *networkHandler) Topology(ctx context.Context, in *TopologyRequest, out *TopologyResponse) error { + return h.NetworkHandler.Topology(ctx, in, out) +} + func (h *networkHandler) ListRoutes(ctx context.Context, in *proto1.Request, out *proto1.ListResponse) error { return h.NetworkHandler.ListRoutes(ctx, in, out) } diff --git a/network/proto/network.pb.go b/network/proto/network.pb.go index 363ef5e4..83f63659 100644 --- a/network/proto/network.pb.go +++ b/network/proto/network.pb.go @@ -137,7 +137,7 @@ func (m *PeerRequest) GetId() string { // PeerResponse is returned by ListPeers type PeerResponse struct { - Peers *Peers `protobuf:"bytes,1,opt,name=peers,proto3" json:"peers,omitempty"` + Peers []*Node `protobuf:"bytes,1,rep,name=peers,proto3" json:"peers,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -168,59 +168,99 @@ func (m *PeerResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PeerResponse proto.InternalMessageInfo -func (m *PeerResponse) GetPeers() *Peers { +func (m *PeerResponse) GetPeers() []*Node { if m != nil { return m.Peers } return nil } -// Peers are node peers -type Peers struct { - // network node - Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` - // node peers - Peers []*Node `protobuf:"bytes,2,rep,name=peers,proto3" json:"peers,omitempty"` +// TopologyRequest list node topology +type TopologyRequest struct { + // node id + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // topology depth + Depth uint64 `protobuf:"varint,2,opt,name=depth,proto3" json:"depth,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *Peers) Reset() { *m = Peers{} } -func (m *Peers) String() string { return proto.CompactTextString(m) } -func (*Peers) ProtoMessage() {} -func (*Peers) Descriptor() ([]byte, []int) { +func (m *TopologyRequest) Reset() { *m = TopologyRequest{} } +func (m *TopologyRequest) String() string { return proto.CompactTextString(m) } +func (*TopologyRequest) ProtoMessage() {} +func (*TopologyRequest) Descriptor() ([]byte, []int) { return fileDescriptor_8571034d60397816, []int{4} } -func (m *Peers) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Peers.Unmarshal(m, b) +func (m *TopologyRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TopologyRequest.Unmarshal(m, b) } -func (m *Peers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Peers.Marshal(b, m, deterministic) +func (m *TopologyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TopologyRequest.Marshal(b, m, deterministic) } -func (m *Peers) XXX_Merge(src proto.Message) { - xxx_messageInfo_Peers.Merge(m, src) +func (m *TopologyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_TopologyRequest.Merge(m, src) } -func (m *Peers) XXX_Size() int { - return xxx_messageInfo_Peers.Size(m) +func (m *TopologyRequest) XXX_Size() int { + return xxx_messageInfo_TopologyRequest.Size(m) } -func (m *Peers) XXX_DiscardUnknown() { - xxx_messageInfo_Peers.DiscardUnknown(m) +func (m *TopologyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_TopologyRequest.DiscardUnknown(m) } -var xxx_messageInfo_Peers proto.InternalMessageInfo +var xxx_messageInfo_TopologyRequest proto.InternalMessageInfo -func (m *Peers) GetNode() *Node { +func (m *TopologyRequest) GetId() string { if m != nil { - return m.Node + return m.Id } - return nil + return "" } -func (m *Peers) GetPeers() []*Node { +func (m *TopologyRequest) GetDepth() uint64 { if m != nil { - return m.Peers + return m.Depth + } + return 0 +} + +// TopologyResponse is returned by Topology +type TopologyResponse struct { + Topology *Topology `protobuf:"bytes,1,opt,name=topology,proto3" json:"topology,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TopologyResponse) Reset() { *m = TopologyResponse{} } +func (m *TopologyResponse) String() string { return proto.CompactTextString(m) } +func (*TopologyResponse) ProtoMessage() {} +func (*TopologyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_8571034d60397816, []int{5} +} + +func (m *TopologyResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TopologyResponse.Unmarshal(m, b) +} +func (m *TopologyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TopologyResponse.Marshal(b, m, deterministic) +} +func (m *TopologyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_TopologyResponse.Merge(m, src) +} +func (m *TopologyResponse) XXX_Size() int { + return xxx_messageInfo_TopologyResponse.Size(m) +} +func (m *TopologyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_TopologyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_TopologyResponse proto.InternalMessageInfo + +func (m *TopologyResponse) GetTopology() *Topology { + if m != nil { + return m.Topology } return nil } @@ -240,7 +280,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_8571034d60397816, []int{5} + return fileDescriptor_8571034d60397816, []int{6} } func (m *Node) XXX_Unmarshal(b []byte) error { @@ -275,6 +315,56 @@ func (m *Node) GetAddress() string { return "" } +// Topology is used to nnounce node neighbourhood +type Topology struct { + // network node + Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + // neighbours + Nodes []*Node `protobuf:"bytes,2,rep,name=nodes,proto3" json:"nodes,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Topology) Reset() { *m = Topology{} } +func (m *Topology) String() string { return proto.CompactTextString(m) } +func (*Topology) ProtoMessage() {} +func (*Topology) Descriptor() ([]byte, []int) { + return fileDescriptor_8571034d60397816, []int{7} +} + +func (m *Topology) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Topology.Unmarshal(m, b) +} +func (m *Topology) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Topology.Marshal(b, m, deterministic) +} +func (m *Topology) XXX_Merge(src proto.Message) { + xxx_messageInfo_Topology.Merge(m, src) +} +func (m *Topology) XXX_Size() int { + return xxx_messageInfo_Topology.Size(m) +} +func (m *Topology) XXX_DiscardUnknown() { + xxx_messageInfo_Topology.DiscardUnknown(m) +} + +var xxx_messageInfo_Topology proto.InternalMessageInfo + +func (m *Topology) GetNode() *Node { + if m != nil { + return m.Node + } + return nil +} + +func (m *Topology) GetNodes() []*Node { + if m != nil { + return m.Nodes + } + return nil +} + // Connect is sent when the node connects to the network type Connect struct { // network mode @@ -288,7 +378,7 @@ func (m *Connect) Reset() { *m = Connect{} } func (m *Connect) String() string { return proto.CompactTextString(m) } func (*Connect) ProtoMessage() {} func (*Connect) Descriptor() ([]byte, []int) { - return fileDescriptor_8571034d60397816, []int{6} + return fileDescriptor_8571034d60397816, []int{8} } func (m *Connect) XXX_Unmarshal(b []byte) error { @@ -329,7 +419,7 @@ func (m *Close) Reset() { *m = Close{} } func (m *Close) String() string { return proto.CompactTextString(m) } func (*Close) ProtoMessage() {} func (*Close) Descriptor() ([]byte, []int) { - return fileDescriptor_8571034d60397816, []int{7} + return fileDescriptor_8571034d60397816, []int{9} } func (m *Close) XXX_Unmarshal(b []byte) error { @@ -370,7 +460,7 @@ func (m *Solicit) Reset() { *m = Solicit{} } func (m *Solicit) String() string { return proto.CompactTextString(m) } func (*Solicit) ProtoMessage() {} func (*Solicit) Descriptor() ([]byte, []int) { - return fileDescriptor_8571034d60397816, []int{8} + return fileDescriptor_8571034d60397816, []int{10} } func (m *Solicit) XXX_Unmarshal(b []byte) error { @@ -413,7 +503,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_8571034d60397816, []int{9} + return fileDescriptor_8571034d60397816, []int{11} } func (m *Peer) XXX_Unmarshal(b []byte) error { @@ -453,8 +543,10 @@ func init() { proto.RegisterType((*ListResponse)(nil), "go.micro.network.ListResponse") proto.RegisterType((*PeerRequest)(nil), "go.micro.network.PeerRequest") proto.RegisterType((*PeerResponse)(nil), "go.micro.network.PeerResponse") - proto.RegisterType((*Peers)(nil), "go.micro.network.Peers") + proto.RegisterType((*TopologyRequest)(nil), "go.micro.network.TopologyRequest") + proto.RegisterType((*TopologyResponse)(nil), "go.micro.network.TopologyResponse") proto.RegisterType((*Node)(nil), "go.micro.network.Node") + proto.RegisterType((*Topology)(nil), "go.micro.network.Topology") proto.RegisterType((*Connect)(nil), "go.micro.network.Connect") proto.RegisterType((*Close)(nil), "go.micro.network.Close") proto.RegisterType((*Solicit)(nil), "go.micro.network.Solicit") @@ -464,28 +556,31 @@ func init() { func init() { proto.RegisterFile("network.proto", fileDescriptor_8571034d60397816) } var fileDescriptor_8571034d60397816 = []byte{ - // 353 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x51, 0x4f, 0xc2, 0x30, - 0x10, 0xc7, 0x19, 0x32, 0x17, 0x6e, 0x60, 0x4c, 0x1f, 0x74, 0x21, 0x99, 0x21, 0x7d, 0x22, 0x46, - 0x86, 0x81, 0xf0, 0xa6, 0x4f, 0x3c, 0xf8, 0x42, 0x88, 0x99, 0x5f, 0x40, 0xd8, 0x2e, 0xd8, 0x08, - 0x3b, 0x6c, 0x4b, 0xfc, 0xd6, 0x7e, 0x06, 0xd3, 0x76, 0x44, 0x84, 0xcc, 0x84, 0xc4, 0xb7, 0xde, - 0xdd, 0xff, 0x7e, 0x77, 0x6d, 0xef, 0xa0, 0x5d, 0xa0, 0xfe, 0x24, 0xf9, 0x9e, 0x6c, 0x24, 0x69, - 0x62, 0x97, 0x4b, 0x4a, 0xd6, 0x22, 0x93, 0x94, 0x94, 0xfe, 0xce, 0x68, 0x29, 0xf4, 0xdb, 0x76, - 0x91, 0x64, 0xb4, 0x1e, 0xd8, 0xc8, 0x60, 0x49, 0x7d, 0x77, 0x90, 0xb4, 0xd5, 0x28, 0x07, 0x36, - 0xb3, 0x34, 0x1c, 0x86, 0xb7, 0x21, 0x9c, 0x0a, 0xa5, 0x53, 0xfc, 0xd8, 0xa2, 0xd2, 0xfc, 0x01, - 0x5a, 0xce, 0x54, 0x1b, 0x2a, 0x14, 0xb2, 0x3b, 0xf0, 0x0b, 0xca, 0x51, 0x45, 0x5e, 0xf7, 0xac, - 0x17, 0x0e, 0xaf, 0x92, 0xc3, 0xaa, 0xc9, 0x8c, 0x72, 0x4c, 0x9d, 0x88, 0xc7, 0x10, 0x3e, 0x23, - 0xca, 0x12, 0xc6, 0x2e, 0xa0, 0x2e, 0xf2, 0xc8, 0xeb, 0x7a, 0xbd, 0x66, 0x5a, 0x17, 0x39, 0x7f, - 0x84, 0x96, 0x0b, 0x97, 0xf0, 0x3e, 0xf8, 0x1b, 0x44, 0xa9, 0xac, 0x24, 0x1c, 0x5e, 0x1f, 0xc3, - 0x8d, 0x5c, 0xa5, 0x4e, 0xc5, 0xe7, 0xe0, 0x5b, 0x9b, 0xdd, 0x42, 0xc3, 0xd4, 0x2b, 0xd3, 0xaa, - 0x7a, 0xb2, 0x1a, 0x73, 0x01, 0x57, 0xa3, 0xfe, 0xf7, 0x05, 0x5c, 0x89, 0x7b, 0x68, 0x18, 0xf3, - 0xb0, 0x73, 0x16, 0x41, 0x30, 0xcf, 0x73, 0x89, 0xca, 0x70, 0x8c, 0x73, 0x67, 0xf2, 0x31, 0x04, - 0x13, 0x2a, 0x0a, 0xcc, 0xf4, 0x29, 0x6d, 0xf1, 0x11, 0xf8, 0x93, 0x15, 0x29, 0x3c, 0x29, 0x69, - 0x0c, 0xc1, 0x0b, 0xad, 0x44, 0x26, 0x4e, 0xab, 0xf5, 0x0a, 0x0d, 0xf3, 0x6e, 0xff, 0xfc, 0x6c, - 0xf6, 0x27, 0x9d, 0x68, 0xf8, 0xe5, 0x41, 0x30, 0x73, 0x7e, 0x36, 0x85, 0xa6, 0x99, 0x20, 0xc3, - 0x52, 0x2c, 0x3e, 0xce, 0xdb, 0x9b, 0xb6, 0xce, 0x4d, 0x55, 0xd8, 0x0d, 0x08, 0xaf, 0xed, 0x68, - 0xee, 0xdf, 0xe3, 0x8a, 0x2e, 0xaa, 0x69, 0xfb, 0xe3, 0xc6, 0x6b, 0xec, 0x09, 0xc0, 0xf2, 0xcd, - 0x02, 0x28, 0x16, 0xfd, 0xe8, 0xcb, 0x95, 0xd8, 0x91, 0xe2, 0xa3, 0xc8, 0xef, 0xb6, 0x16, 0xe7, - 0x76, 0x79, 0x46, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xaf, 0xb8, 0x9b, 0x3f, 0x94, 0x03, 0x00, - 0x00, + // 412 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdf, 0x8a, 0xd3, 0x40, + 0x14, 0xc6, 0x37, 0x31, 0x35, 0xdb, 0x13, 0x57, 0x97, 0x41, 0x24, 0x14, 0x2a, 0x75, 0xae, 0x8a, + 0x68, 0x2a, 0x2d, 0xab, 0x37, 0xde, 0xed, 0x85, 0x20, 0xcb, 0x22, 0xa9, 0x0f, 0xa0, 0xcd, 0x0c, + 0x69, 0xb0, 0xcd, 0x89, 0x33, 0x53, 0xc4, 0xe7, 0xf3, 0xc5, 0x64, 0xfe, 0xa4, 0x89, 0xa6, 0xa9, + 0xe6, 0xae, 0x67, 0xce, 0xf9, 0x7e, 0x5f, 0x72, 0xfa, 0x4d, 0xe0, 0xaa, 0xe4, 0xea, 0x07, 0x8a, + 0x6f, 0x49, 0x25, 0x50, 0x21, 0xb9, 0xce, 0x31, 0xd9, 0x17, 0x99, 0xc0, 0xc4, 0x9d, 0x4f, 0x56, + 0x79, 0xa1, 0xb6, 0x87, 0x4d, 0x92, 0xe1, 0x7e, 0x61, 0x3a, 0x8b, 0x1c, 0x5f, 0xdb, 0x1f, 0x02, + 0x0f, 0x8a, 0x8b, 0x85, 0x51, 0xba, 0xc2, 0x62, 0xe8, 0x15, 0x44, 0x77, 0x85, 0x54, 0x29, 0xff, + 0x7e, 0xe0, 0x52, 0xd1, 0xf7, 0xf0, 0xc8, 0x96, 0xb2, 0xc2, 0x52, 0x72, 0xf2, 0x0a, 0x46, 0x25, + 0x32, 0x2e, 0x63, 0x6f, 0xf6, 0x60, 0x1e, 0x2d, 0x9f, 0x25, 0x7f, 0xbb, 0x26, 0xf7, 0xc8, 0x78, + 0x6a, 0x87, 0xe8, 0x14, 0xa2, 0x4f, 0x9c, 0x0b, 0x07, 0x23, 0x8f, 0xc1, 0x2f, 0x58, 0xec, 0xcd, + 0xbc, 0xf9, 0x38, 0xf5, 0x0b, 0xa6, 0xe1, 0xb6, 0xdd, 0xc0, 0x2b, 0xce, 0xc5, 0x3f, 0xe1, 0x66, + 0x88, 0xbe, 0x83, 0x27, 0x9f, 0xb1, 0xc2, 0x1d, 0xe6, 0x3f, 0x7b, 0x0c, 0xc8, 0x53, 0x18, 0x31, + 0x5e, 0xa9, 0x6d, 0xec, 0xcf, 0xbc, 0x79, 0x90, 0xda, 0x82, 0x7e, 0x84, 0xeb, 0x46, 0xe8, 0xac, + 0xdf, 0xc2, 0xa5, 0x72, 0x67, 0x46, 0x1f, 0x2d, 0x27, 0x5d, 0xf7, 0xa3, 0xea, 0x38, 0x4b, 0xdf, + 0x40, 0xa0, 0x9f, 0xa9, 0xe3, 0x1c, 0x43, 0xf8, 0x95, 0x31, 0xc1, 0xa5, 0x34, 0xde, 0xe3, 0xb4, + 0x2e, 0x29, 0x83, 0xcb, 0x9a, 0x43, 0x5e, 0x42, 0xa0, 0x17, 0xe5, 0x1c, 0xfb, 0xde, 0xd7, 0xcc, + 0x34, 0x9b, 0xf7, 0xff, 0x67, 0xf3, 0x37, 0x10, 0xde, 0x62, 0x59, 0xf2, 0x4c, 0x0d, 0x31, 0xa1, + 0x2b, 0x18, 0xdd, 0xee, 0x50, 0xf2, 0x41, 0xa2, 0x1b, 0x08, 0xd7, 0xb8, 0x2b, 0xb2, 0x62, 0x98, + 0xd7, 0x17, 0x08, 0xf4, 0xbf, 0x3f, 0x74, 0x09, 0x36, 0x21, 0xbd, 0x4b, 0x30, 0x81, 0xb2, 0x43, + 0xcb, 0x5f, 0x3e, 0x84, 0xf7, 0xf6, 0x9c, 0xdc, 0xc1, 0x58, 0x07, 0x59, 0xb3, 0x24, 0x99, 0x76, + 0x75, 0xad, 0xd0, 0x4f, 0x9e, 0xf7, 0xb5, 0x6d, 0x58, 0xe8, 0x45, 0x4d, 0xd3, 0x66, 0x27, 0x69, + 0xad, 0xd4, 0x9f, 0xa2, 0xb5, 0x53, 0x4f, 0x2f, 0xc8, 0xba, 0x15, 0x89, 0x17, 0x67, 0x62, 0xe7, + 0x80, 0xf4, 0xdc, 0xc8, 0x11, 0xfa, 0x01, 0xc0, 0x3c, 0xb4, 0xbe, 0xdc, 0x92, 0xc4, 0x8d, 0xc6, + 0x5d, 0xf7, 0x9a, 0x36, 0xed, 0x74, 0xfe, 0x7c, 0xd7, 0xcd, 0x43, 0xf3, 0x61, 0x58, 0xfd, 0x0e, + 0x00, 0x00, 0xff, 0xff, 0xdc, 0xcf, 0x08, 0x89, 0x70, 0x04, 0x00, 0x00, } diff --git a/network/proto/network.proto b/network/proto/network.proto index 00e526e6..72f600cc 100644 --- a/network/proto/network.proto +++ b/network/proto/network.proto @@ -8,6 +8,7 @@ import "github.com/micro/go-micro/router/proto/router.proto"; service Network { rpc ListNodes(ListRequest) returns (ListResponse) {}; rpc ListPeers(PeerRequest) returns (PeerResponse) {}; + rpc Topology(TopologyRequest) returns (TopologyResponse) {}; rpc ListRoutes(go.micro.router.Request) returns (go.micro.router.ListResponse) {}; } @@ -28,15 +29,20 @@ message PeerRequest { // PeerResponse is returned by ListPeers message PeerResponse { - Peers peers = 1; + repeated Node peers = 1; } -// Peers are node peers -message Peers { - // network node - Node node = 1; - // node peers - repeated Node peers = 2; +// TopologyRequest list node topology +message TopologyRequest { + // node id + string id = 1; + // topology depth + uint64 depth = 2; +} + +// TopologyResponse is returned by Topology +message TopologyResponse { + Topology topology = 1; } // Node is network node @@ -47,6 +53,14 @@ message Node { string address = 2; } +// Topology is used to nnounce node neighbourhood +message Topology { + // network node + Node node = 1; + // neighbours + repeated Node nodes = 2; +} + // Connect is sent when the node connects to the network message Connect { // network mode