Merge pull request #1104 from milosgajdos83/network-hackery
[WIP] Network hackery
This commit is contained in:
		| @@ -6,6 +6,7 @@ import ( | |||||||
| 	"hash/fnv" | 	"hash/fnv" | ||||||
| 	"io" | 	"io" | ||||||
| 	"math" | 	"math" | ||||||
|  | 	"math/rand" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -25,6 +26,7 @@ import ( | |||||||
| 	tun "github.com/micro/go-micro/tunnel/transport" | 	tun "github.com/micro/go-micro/tunnel/transport" | ||||||
| 	"github.com/micro/go-micro/util/backoff" | 	"github.com/micro/go-micro/util/backoff" | ||||||
| 	"github.com/micro/go-micro/util/log" | 	"github.com/micro/go-micro/util/log" | ||||||
|  | 	pbUtil "github.com/micro/go-micro/util/proto" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @@ -36,6 +38,8 @@ var ( | |||||||
| 	DefaultLink = "network" | 	DefaultLink = "network" | ||||||
| 	// MaxConnections is the max number of network client connections | 	// MaxConnections is the max number of network client connections | ||||||
| 	MaxConnections = 3 | 	MaxConnections = 3 | ||||||
|  | 	// MaxPeerErrors is the max number of peer errors before we remove it from network graph | ||||||
|  | 	MaxPeerErrors = 3 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @@ -43,6 +47,8 @@ var ( | |||||||
| 	ErrClientNotFound = errors.New("client not found") | 	ErrClientNotFound = errors.New("client not found") | ||||||
| 	// ErrPeerLinkNotFound is returned when peer link could not be found in tunnel Links | 	// ErrPeerLinkNotFound is returned when peer link could not be found in tunnel Links | ||||||
| 	ErrPeerLinkNotFound = errors.New("peer link not found") | 	ErrPeerLinkNotFound = errors.New("peer link not found") | ||||||
|  | 	// ErrPeerMaxExceeded is returned when peer has reached its max error count limit | ||||||
|  | 	ErrPeerMaxExceeded = errors.New("peer max errors exceeded") | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // network implements Network interface | // network implements Network interface | ||||||
| @@ -159,6 +165,7 @@ func newNetwork(opts ...Option) Network { | |||||||
| 			id:      options.Id, | 			id:      options.Id, | ||||||
| 			address: peerAddress, | 			address: peerAddress, | ||||||
| 			peers:   make(map[string]*node), | 			peers:   make(map[string]*node), | ||||||
|  | 			status:  newStatus(), | ||||||
| 		}, | 		}, | ||||||
| 		options:    options, | 		options:    options, | ||||||
| 		router:     options.Router, | 		router:     options.Router, | ||||||
| @@ -270,9 +277,9 @@ func (n *network) acceptCtrlConn(l tunnel.Listener, recv chan *message) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // handleCtrlConn handles ControlChannel connections |  | ||||||
| // advertise advertises routes to the network | // advertise advertises routes to the network | ||||||
| func (n *network) advertise(advertChan <-chan *router.Advert) { | func (n *network) advertise(advertChan <-chan *router.Advert) { | ||||||
|  | 	rnd := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||||
| 	hasher := fnv.New64() | 	hasher := fnv.New64() | ||||||
| 	for { | 	for { | ||||||
| 		select { | 		select { | ||||||
| @@ -322,11 +329,22 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { | |||||||
| 				Events:    events, | 				Events:    events, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// send the advert to all on the control channel | 			// send the advert to a select number of random peers | ||||||
| 			// since its not a solicitation |  | ||||||
| 			if advert.Type != router.Solicitation { | 			if advert.Type != router.Solicitation { | ||||||
| 				if err := n.sendMsg("advert", ControlChannel, msg); err != nil { | 				// get a list of node peers | ||||||
| 					log.Debugf("Network failed to advertise routes: %v", err) | 				peers := n.Peers() | ||||||
|  |  | ||||||
|  | 				// advertise to max 3 peers | ||||||
|  | 				max := len(peers) | ||||||
|  | 				if max > 3 { | ||||||
|  | 					max = 3 | ||||||
|  | 				} | ||||||
|  | 				for i := 0; i < max; i++ { | ||||||
|  | 					if peer := n.node.GetPeerNode(peers[rnd.Intn(len(peers))].Id()); peer != nil { | ||||||
|  | 						if err := n.sendTo("advert", ControlChannel, peer, msg); err != nil { | ||||||
|  | 							log.Debugf("Network failed to advertise routes to %s: %v", peer.Id(), err) | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| @@ -338,8 +356,17 @@ func (n *network) advertise(advertChan <-chan *router.Advert) { | |||||||
| 				// someone requested the route | 				// someone requested the route | ||||||
| 				n.sendTo("advert", ControlChannel, peer, msg) | 				n.sendTo("advert", ControlChannel, peer, msg) | ||||||
| 			default: | 			default: | ||||||
| 				if err := n.sendMsg("advert", ControlChannel, msg); err != nil { | 				// get a list of node peers | ||||||
| 					log.Debugf("Network failed to advertise routes: %v", err) | 				peers := n.Peers() | ||||||
|  | 				// pick a random peer from the list of peers | ||||||
|  | 				if peer := n.node.GetPeerNode(peers[rnd.Intn(len(peers))].Id()); peer != nil { | ||||||
|  | 					if err := n.sendTo("advert", ControlChannel, peer, msg); err != nil { | ||||||
|  | 						log.Debugf("Network failed to advertise routes to %s: %v, sending multicast", peer.Id(), err) | ||||||
|  | 						// send a multicast message if we fail to send Unicast message | ||||||
|  | 						if err := n.sendMsg("advert", ControlChannel, msg); err != nil { | ||||||
|  | 							log.Debugf("Network failed to advertise routes to %s: %v", peer.Id(), err) | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		case <-n.closed: | 		case <-n.closed: | ||||||
| @@ -354,7 +381,7 @@ func (n *network) initNodes(startup bool) { | |||||||
| 	// NOTE: this condition never fires | 	// NOTE: this condition never fires | ||||||
| 	// as resolveNodes() never returns error | 	// as resolveNodes() never returns error | ||||||
| 	if err != nil && !startup { | 	if err != nil && !startup { | ||||||
| 		log.Debugf("Network failed to resolve nodes: %v", err) | 		log.Debugf("Network failed to init nodes: %v", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -460,6 +487,7 @@ func (n *network) handleNetConn(s tunnel.Session, msg chan *message) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // handleCtrlConn handles ControlChannel connections | ||||||
| func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { | func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { | ||||||
| 	for { | 	for { | ||||||
| 		m := new(transport.Message) | 		m := new(transport.Message) | ||||||
| @@ -493,10 +521,11 @@ func (n *network) handleCtrlConn(s tunnel.Session, msg chan *message) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // getHopCount queries network graph and returns hop count for given router | // getHopCount queries network graph and returns hop count for given router | ||||||
|  | // NOTE: this should be called getHopeMetric | ||||||
| // - Routes for local services have hop count 1 | // - Routes for local services have hop count 1 | ||||||
| // - Routes with ID of adjacent nodes have hop count 2 | // - Routes with ID of adjacent nodes have hop count 10 | ||||||
| // - Routes by peers of the advertiser have hop count 3 | // - Routes by peers of the advertiser have hop count 100 | ||||||
| // - Routes beyond node neighbourhood have hop count 4 | // - Routes beyond node neighbourhood have hop count 1000 | ||||||
| func (n *network) getHopCount(rtr string) int { | func (n *network) getHopCount(rtr string) int { | ||||||
| 	// make sure node.peers are not modified | 	// make sure node.peers are not modified | ||||||
| 	n.node.RLock() | 	n.node.RLock() | ||||||
| @@ -733,8 +762,8 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 			case "connect": | 			case "connect": | ||||||
| 				// mark the time the message has been received | 				// mark the time the message has been received | ||||||
| 				now := time.Now() | 				now := time.Now() | ||||||
| 				pbNetConnect := &pbNet.Connect{} |  | ||||||
|  |  | ||||||
|  | 				pbNetConnect := &pbNet.Connect{} | ||||||
| 				if err := proto.Unmarshal(m.msg.Body, pbNetConnect); err != nil { | 				if err := proto.Unmarshal(m.msg.Body, pbNetConnect); err != nil { | ||||||
| 					log.Debugf("Network tunnel [%s] connect unmarshal error: %v", NetworkChannel, err) | 					log.Debugf("Network tunnel [%s] connect unmarshal error: %v", NetworkChannel, err) | ||||||
| 					continue | 					continue | ||||||
| @@ -752,41 +781,73 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 					address:  pbNetConnect.Node.Address, | 					address:  pbNetConnect.Node.Address, | ||||||
| 					link:     m.msg.Header["Micro-Link"], | 					link:     m.msg.Header["Micro-Link"], | ||||||
| 					peers:    make(map[string]*node), | 					peers:    make(map[string]*node), | ||||||
|  | 					status:   newStatus(), | ||||||
| 					lastSeen: now, | 					lastSeen: now, | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// update peer links | 				// update peer links | ||||||
|  |  | ||||||
|  | 				// TODO: should we do this only if we manage to add a peer | ||||||
|  | 				// What should we do if the peer links failed to be updated? | ||||||
| 				if err := n.updatePeerLinks(peer); err != nil { | 				if err := n.updatePeerLinks(peer); err != nil { | ||||||
| 					log.Debugf("Network failed updating peer links: %s", err) | 					log.Debugf("Network failed updating peer links: %s", err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// add peer to the list of node peers | 				// add peer to the list of node peers | ||||||
| 				if err := n.node.AddPeer(peer); err == ErrPeerExists { | 				if err := n.AddPeer(peer); err == ErrPeerExists { | ||||||
| 					log.Tracef("Network peer exists, refreshing: %s", peer.id) | 					log.Tracef("Network peer exists, refreshing: %s", peer.id) | ||||||
| 					// update lastSeen time for the existing node | 					// update lastSeen time for the peer | ||||||
| 					if err := n.RefreshPeer(peer.id, peer.link, now); err != nil { | 					if err := n.RefreshPeer(peer.id, peer.link, now); err != nil { | ||||||
| 						log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) | 						log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// we send the peer message because someone has sent connect | 				// we send the sync message because someone has sent connect | ||||||
| 				// and wants to know what's on the network. The faster we | 				// and wants to either connect or reconnect to the network | ||||||
| 				// respond the faster we start to converge | 				// The faster it gets the network config (routes and peer graph) | ||||||
|  | 				// the faster the network converges to a stable state | ||||||
| 				// get node peers down to MaxDepth encoded in protobuf |  | ||||||
| 				msg := PeersToProto(n.node, MaxDepth) |  | ||||||
|  |  | ||||||
| 				go func() { | 				go func() { | ||||||
| 					// advertise yourself to the new node | 					// get node peer graph to send back to the connecting node | ||||||
| 					if err := n.sendTo("peer", NetworkChannel, peer, msg); err != nil { | 					node := PeersToProto(n.node, MaxDepth) | ||||||
| 						log.Debugf("Network failed to advertise peers: %v", err) |  | ||||||
|  | 					msg := &pbNet.Sync{ | ||||||
|  | 						Peer: node, | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | 					// get a list of all of our routes | ||||||
|  | 					routes, err := n.options.Router.Table().List() | ||||||
|  | 					switch err { | ||||||
|  | 					case nil: | ||||||
|  | 						// encode the routes to protobuf | ||||||
|  | 						pbRoutes := make([]*pbRtr.Route, 0, len(routes)) | ||||||
|  | 						for _, route := range routes { | ||||||
|  | 							pbRoute := pbUtil.RouteToProto(route) | ||||||
|  | 							pbRoutes = append(pbRoutes, pbRoute) | ||||||
|  | 						} | ||||||
|  | 						// pack the routes into the sync message | ||||||
|  | 						msg.Routes = pbRoutes | ||||||
|  | 					default: | ||||||
|  | 						// we can't list the routes | ||||||
|  | 						log.Debugf("Network node %s failed listing routes: %v", n.id, err) | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					// send sync message to the newly connected peer | ||||||
|  | 					if err := n.sendTo("sync", NetworkChannel, peer, msg); err != nil { | ||||||
|  | 						log.Debugf("Network failed to send sync message: %v", err) | ||||||
|  | 					} | ||||||
|  | 					// wait for a short period of time before sending a solicit message | ||||||
| 					<-time.After(time.Millisecond * 100) | 					<-time.After(time.Millisecond * 100) | ||||||
|  |  | ||||||
|  | 					// send a solicit message when discovering new peer | ||||||
|  | 					// this triggers the node to flush its routing table to the network | ||||||
|  | 					// and leads to faster convergence of the network | ||||||
|  | 					solicit := &pbRtr.Solicit{ | ||||||
|  | 						Id: n.options.Id, | ||||||
|  | 					} | ||||||
|  |  | ||||||
| 					// ask for the new nodes routes | 					// ask for the new nodes routes | ||||||
| 					if err := n.sendTo("solicit", ControlChannel, peer, msg); err != nil { | 					if err := n.sendTo("solicit", ControlChannel, peer, solicit); err != nil { | ||||||
| 						log.Debugf("Network failed to send solicit message: %s", err) | 						log.Debugf("Network failed to send solicit message: %s", err) | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| @@ -796,11 +857,6 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 					default: | 					default: | ||||||
| 						// don't block | 						// don't block | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					// advertise all the routes when a new node has connected |  | ||||||
| 					if err := n.router.Solicit(); err != nil { |  | ||||||
| 						log.Debugf("Network failed to solicit routes: %s", err) |  | ||||||
| 					} |  | ||||||
| 				}() | 				}() | ||||||
| 			case "peer": | 			case "peer": | ||||||
| 				// mark the time the message has been received | 				// mark the time the message has been received | ||||||
| @@ -824,32 +880,37 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 					address:  pbNetPeer.Node.Address, | 					address:  pbNetPeer.Node.Address, | ||||||
| 					link:     m.msg.Header["Micro-Link"], | 					link:     m.msg.Header["Micro-Link"], | ||||||
| 					peers:    make(map[string]*node), | 					peers:    make(map[string]*node), | ||||||
|  | 					status:   newPeerStatus(pbNetPeer), | ||||||
| 					lastSeen: now, | 					lastSeen: now, | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// update peer links | 				// update peer links | ||||||
|  |  | ||||||
|  | 				// TODO: should we do this only if we manage to add a peer | ||||||
|  | 				// What should we do if the peer links failed to be updated? | ||||||
| 				if err := n.updatePeerLinks(peer); err != nil { | 				if err := n.updatePeerLinks(peer); err != nil { | ||||||
| 					log.Debugf("Network failed updating peer links: %s", err) | 					log.Debugf("Network failed updating peer links: %s", err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				// if it's a new peer i.e. we do not have it in our graph, we solicit its routes | ||||||
| 				if err := n.node.AddPeer(peer); err == nil { | 				if err := n.node.AddPeer(peer); err == nil { | ||||||
| 					// send a solicit message when discovering new peer |  | ||||||
| 					msg := &pbRtr.Solicit{ |  | ||||||
| 						Id: n.options.Id, |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					go func() { | 					go func() { | ||||||
|  | 						msg := PeersToProto(n.node, MaxDepth) | ||||||
|  |  | ||||||
| 						// advertise yourself to the peer | 						// advertise yourself to the peer | ||||||
| 						if err := n.sendTo("peer", NetworkChannel, peer, msg); err != nil { | 						if err := n.sendTo("peer", NetworkChannel, peer, msg); err != nil { | ||||||
| 							log.Debugf("Network failed to advertise peers: %v", err) | 							log.Debugf("Network failed to advertise peers: %v", err) | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						// wait for a second |  | ||||||
| 						<-time.After(time.Millisecond * 100) | 						<-time.After(time.Millisecond * 100) | ||||||
|  |  | ||||||
|  | 						// send a solicit message when discovering new peer | ||||||
|  | 						solicit := &pbRtr.Solicit{ | ||||||
|  | 							Id: n.options.Id, | ||||||
|  | 						} | ||||||
|  |  | ||||||
| 						// then solicit this peer | 						// then solicit this peer | ||||||
| 						if err := n.sendTo("solicit", ControlChannel, peer, msg); err != nil { | 						if err := n.sendTo("solicit", ControlChannel, peer, solicit); err != nil { | ||||||
| 							log.Debugf("Network failed to send solicit message: %s", err) | 							log.Debugf("Network failed to send solicit message: %s", err) | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| @@ -867,7 +928,7 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 					}() | 					}() | ||||||
|  |  | ||||||
| 					continue | 					continue | ||||||
| 					// we're expecting any error to be ErrPeerExists | 					// if we already have the peer in our graph, skip further steps | ||||||
| 				} else if err != ErrPeerExists { | 				} else if err != ErrPeerExists { | ||||||
| 					log.Debugf("Network got error adding peer %v", err) | 					log.Debugf("Network got error adding peer %v", err) | ||||||
| 					continue | 					continue | ||||||
| @@ -897,6 +958,75 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 				default: | 				default: | ||||||
| 					// don't block here | 					// don't block here | ||||||
| 				} | 				} | ||||||
|  | 			case "sync": | ||||||
|  | 				// record the timestamp of the message receipt | ||||||
|  | 				now := time.Now() | ||||||
|  |  | ||||||
|  | 				pbNetSync := &pbNet.Sync{} | ||||||
|  | 				if err := proto.Unmarshal(m.msg.Body, pbNetSync); err != nil { | ||||||
|  | 					log.Debugf("Network tunnel [%s] sync unmarshal error: %v", NetworkChannel, err) | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// don't process your own messages | ||||||
|  | 				if pbNetSync.Peer.Node.Id == n.options.Id { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				log.Debugf("Network received sync message from: %s", pbNetSync.Peer.Node.Id) | ||||||
|  |  | ||||||
|  | 				peer := &node{ | ||||||
|  | 					id:       pbNetSync.Peer.Node.Id, | ||||||
|  | 					address:  pbNetSync.Peer.Node.Address, | ||||||
|  | 					link:     m.msg.Header["Micro-Link"], | ||||||
|  | 					peers:    make(map[string]*node), | ||||||
|  | 					status:   newPeerStatus(pbNetSync.Peer), | ||||||
|  | 					lastSeen: now, | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// update peer links | ||||||
|  |  | ||||||
|  | 				// TODO: should we do this only if we manage to add a peer | ||||||
|  | 				// What should we do if the peer links failed to be updated? | ||||||
|  | 				if err := n.updatePeerLinks(peer); err != nil { | ||||||
|  | 					log.Debugf("Network failed updating peer links: %s", err) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// add peer to the list of node peers | ||||||
|  | 				if err := n.node.AddPeer(peer); err == ErrPeerExists { | ||||||
|  | 					log.Tracef("Network peer exists, refreshing: %s", peer.id) | ||||||
|  | 					// update lastSeen time for the existing node | ||||||
|  | 					if err := n.RefreshPeer(peer.id, peer.link, now); err != nil { | ||||||
|  | 						log.Debugf("Network failed refreshing peer %s: %v", peer.id, err) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// when we receive a sync message we update our routing table | ||||||
|  | 				// and send a peer message back to the network to announce our presence | ||||||
|  |  | ||||||
|  | 				// add all the routes we have received in the sync message | ||||||
|  | 				for _, pbRoute := range pbNetSync.Routes { | ||||||
|  | 					route := pbUtil.ProtoToRoute(pbRoute) | ||||||
|  | 					if err := n.router.Table().Create(route); err != nil && err != router.ErrDuplicateRoute { | ||||||
|  | 						log.Debugf("Network node %s failed to add route: %v", n.id, err) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// update your sync timestamp | ||||||
|  | 				// NOTE: this might go away as we will be doing full table advert to random peer | ||||||
|  | 				if err := n.RefreshSync(now); err != nil { | ||||||
|  | 					log.Debugf("Network failed refreshing sync time: %v", err) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				go func() { | ||||||
|  | 					// get node peer graph to send back to the syncing node | ||||||
|  | 					msg := PeersToProto(n.node, MaxDepth) | ||||||
|  |  | ||||||
|  | 					// advertise yourself to the new node | ||||||
|  | 					if err := n.sendTo("peer", NetworkChannel, peer, msg); err != nil { | ||||||
|  | 						log.Debugf("Network failed to advertise peers: %v", err) | ||||||
|  | 					} | ||||||
|  | 				}() | ||||||
| 			case "close": | 			case "close": | ||||||
| 				pbNetClose := &pbNet.Close{} | 				pbNetClose := &pbNet.Close{} | ||||||
| 				if err := proto.Unmarshal(m.msg.Body, pbNetClose); err != nil { | 				if err := proto.Unmarshal(m.msg.Body, pbNetClose); err != nil { | ||||||
| @@ -924,6 +1054,9 @@ func (n *network) processNetChan(listener tunnel.Listener) { | |||||||
| 					log.Debugf("Network failed pruning peer %s routes: %v", peer.id, err) | 					log.Debugf("Network failed pruning peer %s routes: %v", peer.id, err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				// NOTE: we should maybe advertise this to the network so we converge faster on closed nodes | ||||||
|  | 				// as opposed to our waiting until the node eventually gets pruned; something to think about | ||||||
|  |  | ||||||
| 				// delete peer from the peerLinks | 				// delete peer from the peerLinks | ||||||
| 				n.Lock() | 				n.Lock() | ||||||
| 				delete(n.peerLinks, pbNetClose.Node.Address) | 				delete(n.peerLinks, pbNetClose.Node.Address) | ||||||
| @@ -976,12 +1109,15 @@ func (n *network) prunePeerRoutes(peer *node) error { | |||||||
| // seen for a period of time. Also removes all the routes either originated by or routable | // seen for a period of time. Also removes all the routes either originated by or routable | ||||||
| // by the stale nodes. it also resolves nodes periodically and adds them to the tunnel | // by the stale nodes. it also resolves nodes periodically and adds them to the tunnel | ||||||
| func (n *network) manage() { | func (n *network) manage() { | ||||||
|  | 	rnd := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||||
| 	announce := time.NewTicker(AnnounceTime) | 	announce := time.NewTicker(AnnounceTime) | ||||||
| 	defer announce.Stop() | 	defer announce.Stop() | ||||||
| 	prune := time.NewTicker(PruneTime) | 	prune := time.NewTicker(PruneTime) | ||||||
| 	defer prune.Stop() | 	defer prune.Stop() | ||||||
| 	resolve := time.NewTicker(ResolveTime) | 	resolve := time.NewTicker(ResolveTime) | ||||||
| 	defer resolve.Stop() | 	defer resolve.Stop() | ||||||
|  | 	netsync := time.NewTicker(SyncTime) | ||||||
|  | 	defer netsync.Stop() | ||||||
|  |  | ||||||
| 	// list of links we've sent to | 	// list of links we've sent to | ||||||
| 	links := make(map[string]time.Time) | 	links := make(map[string]time.Time) | ||||||
| @@ -1080,7 +1216,7 @@ func (n *network) manage() { | |||||||
|  |  | ||||||
| 				// unknown link and peer so lets do the connect flow | 				// unknown link and peer so lets do the connect flow | ||||||
| 				if err := n.sendTo("connect", NetworkChannel, peer, msg); err != nil { | 				if err := n.sendTo("connect", NetworkChannel, peer, msg); err != nil { | ||||||
| 					log.Debugf("Network failed to advertise peer %s: %v", peer.id, err) | 					log.Debugf("Network failed to connect %s: %v", peer.id, err) | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -1129,6 +1265,46 @@ func (n *network) manage() { | |||||||
| 					log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) | 					log.Debugf("Network failed deleting routes by %s: %v", route.Router, err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 		case <-netsync.C: | ||||||
|  | 			// get a list of node peers | ||||||
|  | 			peers := n.Peers() | ||||||
|  | 			// pick a random peer from the list of peers and request full sync | ||||||
|  | 			peer := n.node.GetPeerNode(peers[rnd.Intn(len(peers))].Id()) | ||||||
|  | 			// skip if we can't find randmly selected peer | ||||||
|  | 			if peer == nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			go func() { | ||||||
|  | 				// get node peer graph to send back to the connecting node | ||||||
|  | 				node := PeersToProto(n.node, MaxDepth) | ||||||
|  |  | ||||||
|  | 				msg := &pbNet.Sync{ | ||||||
|  | 					Peer: node, | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// get a list of all of our routes | ||||||
|  | 				routes, err := n.options.Router.Table().List() | ||||||
|  | 				switch err { | ||||||
|  | 				case nil: | ||||||
|  | 					// encode the routes to protobuf | ||||||
|  | 					pbRoutes := make([]*pbRtr.Route, 0, len(routes)) | ||||||
|  | 					for _, route := range routes { | ||||||
|  | 						pbRoute := pbUtil.RouteToProto(route) | ||||||
|  | 						pbRoutes = append(pbRoutes, pbRoute) | ||||||
|  | 					} | ||||||
|  | 					// pack the routes into the sync message | ||||||
|  | 					msg.Routes = pbRoutes | ||||||
|  | 				default: | ||||||
|  | 					// we can't list the routes | ||||||
|  | 					log.Debugf("Network node %s failed listing routes: %v", n.id, err) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// send sync message to the newly connected peer | ||||||
|  | 				if err := n.sendTo("sync", NetworkChannel, peer, msg); err != nil { | ||||||
|  | 					log.Debugf("Network failed to send sync message: %v", err) | ||||||
|  | 				} | ||||||
|  | 			}() | ||||||
| 		case <-resolve.C: | 		case <-resolve.C: | ||||||
| 			n.initNodes(false) | 			n.initNodes(false) | ||||||
| 		} | 		} | ||||||
| @@ -1160,9 +1336,20 @@ func (n *network) sendTo(method, channel string, peer *node, msg proto.Message) | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Create a unicast connection to the peer but don't do the open/accept flow | 	// Create a unicast connection to the peer but don't do the open/accept flow | ||||||
| 	c, err := n.tunnel.Dial(channel, tunnel.DialWait(false), tunnel.DialLink(peer.link)) | 	c, err := n.tunnel.Dial(channel, tunnel.DialWait(false), tunnel.DialLink(peer.link)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		if peerNode := n.GetPeerNode(peer.id); peerNode != nil { | ||||||
|  | 			log.Debugf("Network found peer %s: %v", peer.id, peerNode) | ||||||
|  | 			// update node status when error happens | ||||||
|  | 			peerNode.status.err.Update(err) | ||||||
|  | 			log.Debugf("Network increment node peer %p %v count to: %d", peerNode, peerNode, peerNode.status.Error().Count()) | ||||||
|  | 			if count := peerNode.status.Error().Count(); count == MaxPeerErrors { | ||||||
|  | 				log.Debugf("Network node peer %v count exceeded %d: %d", peerNode, MaxPeerErrors, peerNode.status.Error().Count()) | ||||||
|  | 				n.PrunePeer(peerNode.id) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	defer c.Close() | 	defer c.Close() | ||||||
| @@ -1187,7 +1374,22 @@ func (n *network) sendTo(method, channel string, peer *node, msg proto.Message) | |||||||
| 		tmsg.Header["Micro-Peer"] = peer.id | 		tmsg.Header["Micro-Peer"] = peer.id | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return c.Send(tmsg) | 	if err := c.Send(tmsg); err != nil { | ||||||
|  | 		// TODO: Lookup peer in our graph | ||||||
|  | 		if peerNode := n.GetPeerNode(peer.id); peerNode != nil { | ||||||
|  | 			log.Debugf("Network found peer %s: %v", peer.id, peerNode) | ||||||
|  | 			// update node status when error happens | ||||||
|  | 			peerNode.status.err.Update(err) | ||||||
|  | 			log.Debugf("Network increment node peer %p %v count to: %d", peerNode, peerNode, peerNode.status.Error().Count()) | ||||||
|  | 			if count := peerNode.status.Error().Count(); count == MaxPeerErrors { | ||||||
|  | 				log.Debugf("Network node peer %v count exceeded %d: %d", peerNode, MaxPeerErrors, peerNode.status.Error().Count()) | ||||||
|  | 				n.PrunePeer(peerNode.id) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // sendMsg sends a message to the tunnel channel | // sendMsg sends a message to the tunnel channel | ||||||
| @@ -1318,6 +1520,9 @@ func (n *network) connect() { | |||||||
| 		if !discovered { | 		if !discovered { | ||||||
| 			// recreate the clients because all the tunnel links are gone | 			// recreate the clients because all the tunnel links are gone | ||||||
| 			// so we haven't send discovery beneath | 			// so we haven't send discovery beneath | ||||||
|  | 			// NOTE: when starting the tunnel for the first time we might be recreating potentially | ||||||
|  | 			// well functioning tunnel clients as "discovered" will be false until the | ||||||
|  | 			// n.discovered channel is read at some point later on. | ||||||
| 			if err := n.createClients(); err != nil { | 			if err := n.createClients(); err != nil { | ||||||
| 				log.Debugf("Failed to recreate network/control clients: %v", err) | 				log.Debugf("Failed to recreate network/control clients: %v", err) | ||||||
| 				continue | 				continue | ||||||
|   | |||||||
| @@ -19,11 +19,27 @@ var ( | |||||||
| 	AnnounceTime = 1 * time.Second | 	AnnounceTime = 1 * time.Second | ||||||
| 	// KeepAliveTime is the time in which we want to have sent a message to a peer | 	// KeepAliveTime is the time in which we want to have sent a message to a peer | ||||||
| 	KeepAliveTime = 30 * time.Second | 	KeepAliveTime = 30 * time.Second | ||||||
|  | 	// SyncTime is the time a network node requests full sync from the network | ||||||
|  | 	SyncTime = 1 * time.Minute | ||||||
| 	// PruneTime defines time interval to periodically check nodes that need to be pruned | 	// PruneTime defines time interval to periodically check nodes that need to be pruned | ||||||
| 	// due to their not announcing their presence within this time interval | 	// due to their not announcing their presence within this time interval | ||||||
| 	PruneTime = 90 * time.Second | 	PruneTime = 90 * time.Second | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Error is network node errors | ||||||
|  | type Error interface { | ||||||
|  | 	// Count is current count of errors | ||||||
|  | 	Count() int | ||||||
|  | 	// Msg is last error message | ||||||
|  | 	Msg() string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Status is node status | ||||||
|  | type Status interface { | ||||||
|  | 	// Error reports error status | ||||||
|  | 	Error() Error | ||||||
|  | } | ||||||
|  |  | ||||||
| // Node is network node | // Node is network node | ||||||
| type Node interface { | type Node interface { | ||||||
| 	// Id is node id | 	// Id is node id | ||||||
| @@ -34,6 +50,8 @@ type Node interface { | |||||||
| 	Peers() []Node | 	Peers() []Node | ||||||
| 	// Network is the network node is in | 	// Network is the network node is in | ||||||
| 	Network() Network | 	Network() Network | ||||||
|  | 	// Status returns node status | ||||||
|  | 	Status() Status | ||||||
| } | } | ||||||
|  |  | ||||||
| // Network is micro network | // Network is micro network | ||||||
|   | |||||||
							
								
								
									
										164
									
								
								network/node.go
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								network/node.go
									
									
									
									
									
								
							| @@ -21,6 +21,73 @@ var ( | |||||||
| 	ErrPeerNotFound = errors.New("peer not found") | 	ErrPeerNotFound = errors.New("peer not found") | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // nerr tracks node errors | ||||||
|  | type nerr struct { | ||||||
|  | 	sync.RWMutex | ||||||
|  | 	count int | ||||||
|  | 	msg   error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Increment increments node error count | ||||||
|  | func (e *nerr) Update(err error) { | ||||||
|  | 	e.Lock() | ||||||
|  | 	defer e.Unlock() | ||||||
|  |  | ||||||
|  | 	e.count++ | ||||||
|  | 	e.msg = err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Count returns node error count | ||||||
|  | func (e *nerr) Count() int { | ||||||
|  | 	e.RLock() | ||||||
|  | 	defer e.RUnlock() | ||||||
|  |  | ||||||
|  | 	return e.count | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (e *nerr) Msg() string { | ||||||
|  | 	e.RLock() | ||||||
|  | 	defer e.RUnlock() | ||||||
|  |  | ||||||
|  | 	if e.msg != nil { | ||||||
|  | 		return e.msg.Error() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // status returns node status | ||||||
|  | type status struct { | ||||||
|  | 	sync.RWMutex | ||||||
|  | 	err *nerr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newStatus creates | ||||||
|  | func newStatus() *status { | ||||||
|  | 	return &status{ | ||||||
|  | 		err: new(nerr), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newPeerStatus(peer *pb.Peer) *status { | ||||||
|  | 	return &status{ | ||||||
|  | 		err: &nerr{ | ||||||
|  | 			count: int(peer.Node.Status.Error.Count), | ||||||
|  | 			msg:   errors.New(peer.Node.Status.Error.Msg), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *status) Error() Error { | ||||||
|  | 	s.RLock() | ||||||
|  | 	defer s.RUnlock() | ||||||
|  |  | ||||||
|  | 	return &nerr{ | ||||||
|  | 		count: s.err.count, | ||||||
|  | 		msg:   s.err.msg, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // node is network node | // node is network node | ||||||
| type node struct { | type node struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| @@ -36,6 +103,10 @@ type node struct { | |||||||
| 	network Network | 	network Network | ||||||
| 	// lastSeen keeps track of node lifetime and updates | 	// lastSeen keeps track of node lifetime and updates | ||||||
| 	lastSeen time.Time | 	lastSeen time.Time | ||||||
|  | 	// lastSync keeps track of node last sync request | ||||||
|  | 	lastSync time.Time | ||||||
|  | 	// err tracks node status | ||||||
|  | 	status *status | ||||||
| } | } | ||||||
|  |  | ||||||
| // Id is node ide | // Id is node ide | ||||||
| @@ -53,6 +124,19 @@ func (n *node) Network() Network { | |||||||
| 	return n.network | 	return n.network | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Status returns node status | ||||||
|  | func (n *node) Status() Status { | ||||||
|  | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
|  | 	return &status{ | ||||||
|  | 		err: &nerr{ | ||||||
|  | 			count: n.status.err.count, | ||||||
|  | 			msg:   n.status.err.msg, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // walk walks the node graph until some condition is met | // walk walks the node graph until some condition is met | ||||||
| func (n *node) walk(until func(peer *node) bool, action func(parent, peer *node)) map[string]*node { | func (n *node) walk(until func(peer *node) bool, action func(parent, peer *node)) map[string]*node { | ||||||
| 	// track the visited nodes | 	// track the visited nodes | ||||||
| @@ -75,9 +159,9 @@ func (n *node) walk(until func(peer *node) bool, action func(parent, peer *node) | |||||||
| 		// iterate through all of the node peers | 		// iterate through all of the node peers | ||||||
| 		// mark the visited nodes; enqueue the non-visted | 		// mark the visited nodes; enqueue the non-visted | ||||||
| 		for id, peer := range qnode.Value.(*node).peers { | 		for id, peer := range qnode.Value.(*node).peers { | ||||||
|  | 			action(qnode.Value.(*node), peer) | ||||||
| 			if _, ok := visited[id]; !ok { | 			if _, ok := visited[id]; !ok { | ||||||
| 				visited[id] = peer | 				visited[id] = peer | ||||||
| 				action(qnode.Value.(*node), peer) |  | ||||||
| 				queue.PushBack(peer) | 				queue.PushBack(peer) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -94,7 +178,28 @@ func (n *node) AddPeer(peer *node) error { | |||||||
| 	n.Lock() | 	n.Lock() | ||||||
| 	defer n.Unlock() | 	defer n.Unlock() | ||||||
|  |  | ||||||
|  | 	// get node topology: we need to check if the peer | ||||||
|  | 	// we are trying to add is already in our graph | ||||||
|  | 	top := n.getTopology(MaxDepth) | ||||||
|  |  | ||||||
|  | 	untilFoundPeer := func(n *node) bool { | ||||||
|  | 		return n.id == peer.id | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	justWalk := func(paent, node *node) {} | ||||||
|  |  | ||||||
|  | 	visited := top.walk(untilFoundPeer, justWalk) | ||||||
|  |  | ||||||
|  | 	peerNode, inTop := visited[peer.id] | ||||||
|  |  | ||||||
| 	if _, ok := n.peers[peer.id]; !ok { | 	if _, ok := n.peers[peer.id]; !ok { | ||||||
|  | 		if inTop { | ||||||
|  | 			// just create a new edge to the existing peer | ||||||
|  | 			// but make sure you update the peer link | ||||||
|  | 			peerNode.link = peer.link | ||||||
|  | 			n.peers[peer.id] = peerNode | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
| 		n.peers[peer.id] = peer | 		n.peers[peer.id] = peer | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| @@ -127,7 +232,7 @@ func (n *node) UpdatePeer(peer *node) error { | |||||||
| 	return ErrPeerNotFound | 	return ErrPeerNotFound | ||||||
| } | } | ||||||
|  |  | ||||||
| // RefreshPeer updates node timestamp | // RefreshPeer updates node last seen timestamp | ||||||
| // It returns false if the peer has not been found. | // It returns false if the peer has not been found. | ||||||
| func (n *node) RefreshPeer(id, link string, now time.Time) error { | func (n *node) RefreshPeer(id, link string, now time.Time) error { | ||||||
| 	n.Lock() | 	n.Lock() | ||||||
| @@ -146,6 +251,16 @@ func (n *node) RefreshPeer(id, link string, now time.Time) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // RefreshSync refreshes nodes sync time | ||||||
|  | func (n *node) RefreshSync(now time.Time) error { | ||||||
|  | 	n.Lock() | ||||||
|  | 	defer n.Unlock() | ||||||
|  |  | ||||||
|  | 	n.lastSync = now | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Nodes returns a slice of all nodes in the whole node topology | // Nodes returns a slice of all nodes in the whole node topology | ||||||
| func (n *node) Nodes() []Node { | func (n *node) Nodes() []Node { | ||||||
| 	// we need to freeze the network graph here | 	// we need to freeze the network graph here | ||||||
| @@ -217,7 +332,25 @@ func (n *node) DeletePeerNode(id string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // PruneStalePeerNodes prune the peers that have not been seen for longer than given time | // PrunePeer prunes the peers with the given id | ||||||
|  | func (n *node) PrunePeer(id string) { | ||||||
|  | 	n.Lock() | ||||||
|  | 	defer n.Unlock() | ||||||
|  |  | ||||||
|  | 	untilNoMorePeers := func(node *node) bool { | ||||||
|  | 		return node == nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	prunePeer := func(parent, node *node) { | ||||||
|  | 		if node.id != n.id && node.id == id { | ||||||
|  | 			delete(parent.peers, node.id) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	n.walk(untilNoMorePeers, prunePeer) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PruneStalePeerNodes prunes the peers that have not been seen for longer than pruneTime | ||||||
| // It returns a map of the the nodes that got pruned | // It returns a map of the the nodes that got pruned | ||||||
| func (n *node) PruneStalePeers(pruneTime time.Duration) map[string]*node { | func (n *node) PruneStalePeers(pruneTime time.Duration) map[string]*node { | ||||||
| 	n.Lock() | 	n.Lock() | ||||||
| @@ -249,6 +382,7 @@ func (n *node) getTopology(depth uint) *node { | |||||||
| 		address:  n.address, | 		address:  n.address, | ||||||
| 		peers:    make(map[string]*node), | 		peers:    make(map[string]*node), | ||||||
| 		network:  n.network, | 		network:  n.network, | ||||||
|  | 		status:   n.status, | ||||||
| 		lastSeen: n.lastSeen, | 		lastSeen: n.lastSeen, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -297,9 +431,15 @@ func (n *node) Peers() []Node { | |||||||
| // UnpackPeerTopology unpacks pb.Peer into node topology of given depth | // UnpackPeerTopology unpacks pb.Peer into node topology of given depth | ||||||
| func UnpackPeerTopology(pbPeer *pb.Peer, lastSeen time.Time, depth uint) *node { | func UnpackPeerTopology(pbPeer *pb.Peer, lastSeen time.Time, depth uint) *node { | ||||||
| 	peerNode := &node{ | 	peerNode := &node{ | ||||||
| 		id:       pbPeer.Node.Id, | 		id:      pbPeer.Node.Id, | ||||||
| 		address:  pbPeer.Node.Address, | 		address: pbPeer.Node.Address, | ||||||
| 		peers:    make(map[string]*node), | 		peers:   make(map[string]*node), | ||||||
|  | 		status: &status{ | ||||||
|  | 			err: &nerr{ | ||||||
|  | 				count: int(pbPeer.Node.Status.Error.Count), | ||||||
|  | 				msg:   errors.New(pbPeer.Node.Status.Error.Msg), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 		lastSeen: lastSeen, | 		lastSeen: lastSeen, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -326,6 +466,12 @@ func peerProtoTopology(peer Node, depth uint) *pb.Peer { | |||||||
| 	node := &pb.Node{ | 	node := &pb.Node{ | ||||||
| 		Id:      peer.Id(), | 		Id:      peer.Id(), | ||||||
| 		Address: peer.Address(), | 		Address: peer.Address(), | ||||||
|  | 		Status: &pb.Status{ | ||||||
|  | 			Error: &pb.Error{ | ||||||
|  | 				Count: uint32(peer.Status().Error().Count()), | ||||||
|  | 				Msg:   peer.Status().Error().Msg(), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// set the network name if network is not nil | 	// set the network name if network is not nil | ||||||
| @@ -361,6 +507,12 @@ func PeersToProto(node Node, depth uint) *pb.Peer { | |||||||
| 	pbNode := &pb.Node{ | 	pbNode := &pb.Node{ | ||||||
| 		Id:      node.Id(), | 		Id:      node.Id(), | ||||||
| 		Address: node.Address(), | 		Address: node.Address(), | ||||||
|  | 		Status: &pb.Status{ | ||||||
|  | 			Error: &pb.Error{ | ||||||
|  | 				Count: uint32(node.Status().Error().Count()), | ||||||
|  | 				Msg:   node.Status().Error().Msg(), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// set the network name if network is not nil | 	// set the network name if network is not nil | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ func testSetup() *node { | |||||||
| 		address: testNodeAddress, | 		address: testNodeAddress, | ||||||
| 		peers:   make(map[string]*node), | 		peers:   make(map[string]*node), | ||||||
| 		network: newNetwork(Name(testNodeNetName)), | 		network: newNetwork(Name(testNodeNetName)), | ||||||
|  | 		status:  newStatus(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// add some peers to the node | 	// add some peers to the node | ||||||
| @@ -30,6 +31,7 @@ func testSetup() *node { | |||||||
| 			address: testNode.address + "-" + id, | 			address: testNode.address + "-" + id, | ||||||
| 			peers:   make(map[string]*node), | 			peers:   make(map[string]*node), | ||||||
| 			network: testNode.network, | 			network: testNode.network, | ||||||
|  | 			status:  newStatus(), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -41,6 +43,7 @@ func testSetup() *node { | |||||||
| 			address: testNode.address + "-" + id, | 			address: testNode.address + "-" + id, | ||||||
| 			peers:   make(map[string]*node), | 			peers:   make(map[string]*node), | ||||||
| 			network: testNode.network, | 			network: testNode.network, | ||||||
|  | 			status:  newStatus(), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -215,21 +218,53 @@ func TestDeletePeerNode(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestPruneStalePeerNodes(t *testing.T) { | func TestPrunePeer(t *testing.T) { | ||||||
| 	// complicated node graph | 	// complicated node graph | ||||||
| 	node := testSetup() | 	node := testSetup() | ||||||
|  |  | ||||||
| 	nodes := node.Nodes() | 	before := node.Nodes() | ||||||
|  |  | ||||||
|  | 	node.PrunePeer("peer3") | ||||||
|  |  | ||||||
|  | 	now := node.Nodes() | ||||||
|  |  | ||||||
|  | 	if len(now) != len(before)-1 { | ||||||
|  | 		t.Errorf("Expected pruned node count: %d, got: %d", len(before)-1, len(now)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPruneStalePeers(t *testing.T) { | ||||||
|  | 	// complicated node graph | ||||||
|  | 	node := testSetup() | ||||||
|  | 	nodes := node.Nodes() | ||||||
|  | 	// this will delete all nodes besides the root node | ||||||
| 	pruneTime := 10 * time.Millisecond | 	pruneTime := 10 * time.Millisecond | ||||||
| 	time.Sleep(pruneTime) | 	time.Sleep(pruneTime) | ||||||
|  |  | ||||||
| 	// should delete all nodes besides node | 	// should delete all nodes besides (root) node | ||||||
| 	pruned := node.PruneStalePeers(pruneTime) | 	pruned := node.PruneStalePeers(pruneTime) | ||||||
|  |  | ||||||
| 	if len(pruned) != len(nodes)-1 { | 	if len(pruned) != len(nodes)-1 { | ||||||
| 		t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-1, len(pruned)) | 		t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-1, len(pruned)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// complicated node graph | ||||||
|  | 	node = testSetup() | ||||||
|  | 	nodes = node.Nodes() | ||||||
|  |  | ||||||
|  | 	// set prune time to 100ms and wait for half of it | ||||||
|  | 	pruneTime = 100 * time.Millisecond | ||||||
|  | 	time.Sleep(pruneTime) | ||||||
|  |  | ||||||
|  | 	// update the time of peer1 | ||||||
|  | 	node.peers["peer1"].lastSeen = time.Now() | ||||||
|  |  | ||||||
|  | 	// should prune all but the root nodes and peer1 | ||||||
|  | 	pruned = node.PruneStalePeers(pruneTime) | ||||||
|  |  | ||||||
|  | 	if len(pruned) != len(nodes)-2 { | ||||||
|  | 		t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-2, len(pruned)) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestUnpackPeerTopology(t *testing.T) { | func TestUnpackPeerTopology(t *testing.T) { | ||||||
| @@ -237,6 +272,9 @@ func TestUnpackPeerTopology(t *testing.T) { | |||||||
| 		Node: &pb.Node{ | 		Node: &pb.Node{ | ||||||
| 			Id:      "newPeer", | 			Id:      "newPeer", | ||||||
| 			Address: "newPeerAddress", | 			Address: "newPeerAddress", | ||||||
|  | 			Status: &pb.Status{ | ||||||
|  | 				Error: &pb.Error{}, | ||||||
|  | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		Peers: make([]*pb.Peer, 0), | 		Peers: make([]*pb.Peer, 0), | ||||||
| 	} | 	} | ||||||
| @@ -252,12 +290,18 @@ func TestUnpackPeerTopology(t *testing.T) { | |||||||
| 	pbPeer1Node := &pb.Node{ | 	pbPeer1Node := &pb.Node{ | ||||||
| 		Id:      peer1.id, | 		Id:      peer1.id, | ||||||
| 		Address: peer1.address, | 		Address: peer1.address, | ||||||
|  | 		Status: &pb.Status{ | ||||||
|  | 			Error: &pb.Error{}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pbPeer111 := &pb.Peer{ | 	pbPeer111 := &pb.Peer{ | ||||||
| 		Node: &pb.Node{ | 		Node: &pb.Node{ | ||||||
| 			Id:      "peer111", | 			Id:      "peer111", | ||||||
| 			Address: "peer111Address", | 			Address: "peer111Address", | ||||||
|  | 			Status: &pb.Status{ | ||||||
|  | 				Error: &pb.Error{}, | ||||||
|  | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		Peers: make([]*pb.Peer, 0), | 		Peers: make([]*pb.Peer, 0), | ||||||
| 	} | 	} | ||||||
| @@ -266,6 +310,9 @@ func TestUnpackPeerTopology(t *testing.T) { | |||||||
| 		Node: &pb.Node{ | 		Node: &pb.Node{ | ||||||
| 			Id:      "peer121", | 			Id:      "peer121", | ||||||
| 			Address: "peer121Address", | 			Address: "peer121Address", | ||||||
|  | 			Status: &pb.Status{ | ||||||
|  | 				Error: &pb.Error{}, | ||||||
|  | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		Peers: make([]*pb.Peer, 0), | 		Peers: make([]*pb.Peer, 0), | ||||||
| 	} | 	} | ||||||
| @@ -292,6 +339,7 @@ func TestPeersToProto(t *testing.T) { | |||||||
| 		address: testNodeAddress, | 		address: testNodeAddress, | ||||||
| 		peers:   make(map[string]*node), | 		peers:   make(map[string]*node), | ||||||
| 		network: newNetwork(Name(testNodeNetName)), | 		network: newNetwork(Name(testNodeNetName)), | ||||||
|  | 		status:  newStatus(), | ||||||
| 	} | 	} | ||||||
| 	topCount := 0 | 	topCount := 0 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | // Code generated by protoc-gen-go. DO NOT EDIT. | ||||||
| // source: github.com/micro/go-micro/network/proto/network.proto | // source: network.proto | ||||||
|  |  | ||||||
| package go_micro_network | package go_micro_network | ||||||
|  |  | ||||||
| @@ -37,7 +37,7 @@ func (m *Query) Reset()         { *m = Query{} } | |||||||
| func (m *Query) String() string { return proto.CompactTextString(m) } | func (m *Query) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Query) ProtoMessage()    {} | func (*Query) ProtoMessage()    {} | ||||||
| func (*Query) Descriptor() ([]byte, []int) { | func (*Query) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{0} | 	return fileDescriptor_8571034d60397816, []int{0} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Query) XXX_Unmarshal(b []byte) error { | func (m *Query) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -104,7 +104,7 @@ func (m *ConnectRequest) Reset()         { *m = ConnectRequest{} } | |||||||
| func (m *ConnectRequest) String() string { return proto.CompactTextString(m) } | func (m *ConnectRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ConnectRequest) ProtoMessage()    {} | func (*ConnectRequest) ProtoMessage()    {} | ||||||
| func (*ConnectRequest) Descriptor() ([]byte, []int) { | func (*ConnectRequest) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{1} | 	return fileDescriptor_8571034d60397816, []int{1} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *ConnectRequest) XXX_Unmarshal(b []byte) error { | func (m *ConnectRequest) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -142,7 +142,7 @@ func (m *ConnectResponse) Reset()         { *m = ConnectResponse{} } | |||||||
| func (m *ConnectResponse) String() string { return proto.CompactTextString(m) } | func (m *ConnectResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ConnectResponse) ProtoMessage()    {} | func (*ConnectResponse) ProtoMessage()    {} | ||||||
| func (*ConnectResponse) Descriptor() ([]byte, []int) { | func (*ConnectResponse) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{2} | 	return fileDescriptor_8571034d60397816, []int{2} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *ConnectResponse) XXX_Unmarshal(b []byte) error { | func (m *ConnectResponse) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -176,7 +176,7 @@ func (m *NodesRequest) Reset()         { *m = NodesRequest{} } | |||||||
| func (m *NodesRequest) String() string { return proto.CompactTextString(m) } | func (m *NodesRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*NodesRequest) ProtoMessage()    {} | func (*NodesRequest) ProtoMessage()    {} | ||||||
| func (*NodesRequest) Descriptor() ([]byte, []int) { | func (*NodesRequest) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{3} | 	return fileDescriptor_8571034d60397816, []int{3} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *NodesRequest) XXX_Unmarshal(b []byte) error { | func (m *NodesRequest) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -217,7 +217,7 @@ func (m *NodesResponse) Reset()         { *m = NodesResponse{} } | |||||||
| func (m *NodesResponse) String() string { return proto.CompactTextString(m) } | func (m *NodesResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*NodesResponse) ProtoMessage()    {} | func (*NodesResponse) ProtoMessage()    {} | ||||||
| func (*NodesResponse) Descriptor() ([]byte, []int) { | func (*NodesResponse) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{4} | 	return fileDescriptor_8571034d60397816, []int{4} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *NodesResponse) XXX_Unmarshal(b []byte) error { | func (m *NodesResponse) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -257,7 +257,7 @@ func (m *GraphRequest) Reset()         { *m = GraphRequest{} } | |||||||
| func (m *GraphRequest) String() string { return proto.CompactTextString(m) } | func (m *GraphRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*GraphRequest) ProtoMessage()    {} | func (*GraphRequest) ProtoMessage()    {} | ||||||
| func (*GraphRequest) Descriptor() ([]byte, []int) { | func (*GraphRequest) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{5} | 	return fileDescriptor_8571034d60397816, []int{5} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *GraphRequest) XXX_Unmarshal(b []byte) error { | func (m *GraphRequest) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -296,7 +296,7 @@ func (m *GraphResponse) Reset()         { *m = GraphResponse{} } | |||||||
| func (m *GraphResponse) String() string { return proto.CompactTextString(m) } | func (m *GraphResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*GraphResponse) ProtoMessage()    {} | func (*GraphResponse) ProtoMessage()    {} | ||||||
| func (*GraphResponse) Descriptor() ([]byte, []int) { | func (*GraphResponse) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{6} | 	return fileDescriptor_8571034d60397816, []int{6} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *GraphResponse) XXX_Unmarshal(b []byte) error { | func (m *GraphResponse) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -336,7 +336,7 @@ func (m *RoutesRequest) Reset()         { *m = RoutesRequest{} } | |||||||
| func (m *RoutesRequest) String() string { return proto.CompactTextString(m) } | func (m *RoutesRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*RoutesRequest) ProtoMessage()    {} | func (*RoutesRequest) ProtoMessage()    {} | ||||||
| func (*RoutesRequest) Descriptor() ([]byte, []int) { | func (*RoutesRequest) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{7} | 	return fileDescriptor_8571034d60397816, []int{7} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *RoutesRequest) XXX_Unmarshal(b []byte) error { | func (m *RoutesRequest) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -375,7 +375,7 @@ func (m *RoutesResponse) Reset()         { *m = RoutesResponse{} } | |||||||
| func (m *RoutesResponse) String() string { return proto.CompactTextString(m) } | func (m *RoutesResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*RoutesResponse) ProtoMessage()    {} | func (*RoutesResponse) ProtoMessage()    {} | ||||||
| func (*RoutesResponse) Descriptor() ([]byte, []int) { | func (*RoutesResponse) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{8} | 	return fileDescriptor_8571034d60397816, []int{8} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *RoutesResponse) XXX_Unmarshal(b []byte) error { | func (m *RoutesResponse) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -413,7 +413,7 @@ func (m *ServicesRequest) Reset()         { *m = ServicesRequest{} } | |||||||
| func (m *ServicesRequest) String() string { return proto.CompactTextString(m) } | func (m *ServicesRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ServicesRequest) ProtoMessage()    {} | func (*ServicesRequest) ProtoMessage()    {} | ||||||
| func (*ServicesRequest) Descriptor() ([]byte, []int) { | func (*ServicesRequest) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{9} | 	return fileDescriptor_8571034d60397816, []int{9} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *ServicesRequest) XXX_Unmarshal(b []byte) error { | func (m *ServicesRequest) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -445,7 +445,7 @@ func (m *ServicesResponse) Reset()         { *m = ServicesResponse{} } | |||||||
| func (m *ServicesResponse) String() string { return proto.CompactTextString(m) } | func (m *ServicesResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ServicesResponse) ProtoMessage()    {} | func (*ServicesResponse) ProtoMessage()    {} | ||||||
| func (*ServicesResponse) Descriptor() ([]byte, []int) { | func (*ServicesResponse) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{10} | 	return fileDescriptor_8571034d60397816, []int{10} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *ServicesResponse) XXX_Unmarshal(b []byte) error { | func (m *ServicesResponse) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -473,6 +473,164 @@ func (m *ServicesResponse) GetServices() []string { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type StatusRequest struct { | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *StatusRequest) Reset()         { *m = StatusRequest{} } | ||||||
|  | func (m *StatusRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*StatusRequest) ProtoMessage()    {} | ||||||
|  | func (*StatusRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{11} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *StatusRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_StatusRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *StatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_StatusRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *StatusRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_StatusRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *StatusRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_StatusRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *StatusRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_StatusRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_StatusRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | type StatusResponse struct { | ||||||
|  | 	Status               *Status  `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *StatusResponse) Reset()         { *m = StatusResponse{} } | ||||||
|  | func (m *StatusResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*StatusResponse) ProtoMessage()    {} | ||||||
|  | func (*StatusResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{12} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *StatusResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_StatusResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *StatusResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_StatusResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *StatusResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_StatusResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *StatusResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_StatusResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_StatusResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *StatusResponse) GetStatus() *Status { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Status | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Error tracks network errors | ||||||
|  | type Error struct { | ||||||
|  | 	Count                uint32   `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` | ||||||
|  | 	Msg                  string   `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Error) Reset()         { *m = Error{} } | ||||||
|  | func (m *Error) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Error) ProtoMessage()    {} | ||||||
|  | func (*Error) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{13} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Error) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Error.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Error.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Error) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Error.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Error) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Error.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Error) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Error.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Error proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Error) GetCount() uint32 { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Count | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Error) GetMsg() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Msg | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Status is node status | ||||||
|  | type Status struct { | ||||||
|  | 	Error                *Error   `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Status) Reset()         { *m = Status{} } | ||||||
|  | func (m *Status) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Status) ProtoMessage()    {} | ||||||
|  | func (*Status) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{14} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Status) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Status.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Status.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Status) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Status.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Status) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Status.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Status) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Status.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Status proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Status) GetError() *Error { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Error | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Node is network node | // Node is network node | ||||||
| type Node struct { | type Node struct { | ||||||
| 	// node id | 	// node id | ||||||
| @@ -482,17 +640,19 @@ type Node struct { | |||||||
| 	// the network | 	// the network | ||||||
| 	Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` | 	Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` | ||||||
| 	// associated metadata | 	// associated metadata | ||||||
| 	Metadata             map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` | 	Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` | ||||||
| 	XXX_NoUnkeyedLiteral struct{}          `json:"-"` | 	// node status | ||||||
| 	XXX_unrecognized     []byte            `json:"-"` | 	Status               *Status  `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` | ||||||
| 	XXX_sizecache        int32             `json:"-"` | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Node) Reset()         { *m = Node{} } | func (m *Node) Reset()         { *m = Node{} } | ||||||
| func (m *Node) String() string { return proto.CompactTextString(m) } | func (m *Node) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Node) ProtoMessage()    {} | func (*Node) ProtoMessage()    {} | ||||||
| func (*Node) Descriptor() ([]byte, []int) { | func (*Node) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{11} | 	return fileDescriptor_8571034d60397816, []int{15} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Node) XXX_Unmarshal(b []byte) error { | func (m *Node) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -541,6 +701,13 @@ func (m *Node) GetMetadata() map[string]string { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (m *Node) GetStatus() *Status { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Status | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Connect is sent when the node connects to the network | // Connect is sent when the node connects to the network | ||||||
| type Connect struct { | type Connect struct { | ||||||
| 	// network mode | 	// network mode | ||||||
| @@ -554,7 +721,7 @@ func (m *Connect) Reset()         { *m = Connect{} } | |||||||
| func (m *Connect) String() string { return proto.CompactTextString(m) } | func (m *Connect) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Connect) ProtoMessage()    {} | func (*Connect) ProtoMessage()    {} | ||||||
| func (*Connect) Descriptor() ([]byte, []int) { | func (*Connect) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{12} | 	return fileDescriptor_8571034d60397816, []int{16} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Connect) XXX_Unmarshal(b []byte) error { | func (m *Connect) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -595,7 +762,7 @@ func (m *Close) Reset()         { *m = Close{} } | |||||||
| func (m *Close) String() string { return proto.CompactTextString(m) } | func (m *Close) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Close) ProtoMessage()    {} | func (*Close) ProtoMessage()    {} | ||||||
| func (*Close) Descriptor() ([]byte, []int) { | func (*Close) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{13} | 	return fileDescriptor_8571034d60397816, []int{17} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Close) XXX_Unmarshal(b []byte) error { | func (m *Close) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -638,7 +805,7 @@ func (m *Peer) Reset()         { *m = Peer{} } | |||||||
| func (m *Peer) String() string { return proto.CompactTextString(m) } | func (m *Peer) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Peer) ProtoMessage()    {} | func (*Peer) ProtoMessage()    {} | ||||||
| func (*Peer) Descriptor() ([]byte, []int) { | func (*Peer) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_0b7953b26a7c4730, []int{14} | 	return fileDescriptor_8571034d60397816, []int{18} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *Peer) XXX_Unmarshal(b []byte) error { | func (m *Peer) XXX_Unmarshal(b []byte) error { | ||||||
| @@ -673,6 +840,56 @@ func (m *Peer) GetPeers() []*Peer { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Sync is network sync message | ||||||
|  | type Sync struct { | ||||||
|  | 	// peer origin | ||||||
|  | 	Peer *Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` | ||||||
|  | 	// node routes | ||||||
|  | 	Routes               []*proto1.Route `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{}        `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte          `json:"-"` | ||||||
|  | 	XXX_sizecache        int32           `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Sync) Reset()         { *m = Sync{} } | ||||||
|  | func (m *Sync) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Sync) ProtoMessage()    {} | ||||||
|  | func (*Sync) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{19} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Sync) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Sync.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Sync) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Sync.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Sync) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Sync.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Sync) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Sync.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Sync) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Sync.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Sync proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Sync) GetPeer() *Peer { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Peer | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Sync) GetRoutes() []*proto1.Route { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Routes | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	proto.RegisterType((*Query)(nil), "go.micro.network.Query") | 	proto.RegisterType((*Query)(nil), "go.micro.network.Query") | ||||||
| 	proto.RegisterType((*ConnectRequest)(nil), "go.micro.network.ConnectRequest") | 	proto.RegisterType((*ConnectRequest)(nil), "go.micro.network.ConnectRequest") | ||||||
| @@ -685,53 +902,63 @@ func init() { | |||||||
| 	proto.RegisterType((*RoutesResponse)(nil), "go.micro.network.RoutesResponse") | 	proto.RegisterType((*RoutesResponse)(nil), "go.micro.network.RoutesResponse") | ||||||
| 	proto.RegisterType((*ServicesRequest)(nil), "go.micro.network.ServicesRequest") | 	proto.RegisterType((*ServicesRequest)(nil), "go.micro.network.ServicesRequest") | ||||||
| 	proto.RegisterType((*ServicesResponse)(nil), "go.micro.network.ServicesResponse") | 	proto.RegisterType((*ServicesResponse)(nil), "go.micro.network.ServicesResponse") | ||||||
|  | 	proto.RegisterType((*StatusRequest)(nil), "go.micro.network.StatusRequest") | ||||||
|  | 	proto.RegisterType((*StatusResponse)(nil), "go.micro.network.StatusResponse") | ||||||
|  | 	proto.RegisterType((*Error)(nil), "go.micro.network.Error") | ||||||
|  | 	proto.RegisterType((*Status)(nil), "go.micro.network.Status") | ||||||
| 	proto.RegisterType((*Node)(nil), "go.micro.network.Node") | 	proto.RegisterType((*Node)(nil), "go.micro.network.Node") | ||||||
| 	proto.RegisterMapType((map[string]string)(nil), "go.micro.network.Node.MetadataEntry") | 	proto.RegisterMapType((map[string]string)(nil), "go.micro.network.Node.MetadataEntry") | ||||||
| 	proto.RegisterType((*Connect)(nil), "go.micro.network.Connect") | 	proto.RegisterType((*Connect)(nil), "go.micro.network.Connect") | ||||||
| 	proto.RegisterType((*Close)(nil), "go.micro.network.Close") | 	proto.RegisterType((*Close)(nil), "go.micro.network.Close") | ||||||
| 	proto.RegisterType((*Peer)(nil), "go.micro.network.Peer") | 	proto.RegisterType((*Peer)(nil), "go.micro.network.Peer") | ||||||
|  | 	proto.RegisterType((*Sync)(nil), "go.micro.network.Sync") | ||||||
| } | } | ||||||
|  |  | ||||||
| func init() { | func init() { proto.RegisterFile("network.proto", fileDescriptor_8571034d60397816) } | ||||||
| 	proto.RegisterFile("github.com/micro/go-micro/network/proto/network.proto", fileDescriptor_0b7953b26a7c4730) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var fileDescriptor_0b7953b26a7c4730 = []byte{ | var fileDescriptor_8571034d60397816 = []byte{ | ||||||
| 	// 576 bytes of a gzipped FileDescriptorProto | 	// 678 bytes of a gzipped FileDescriptorProto | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x61, 0x6a, 0xdb, 0x4c, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdd, 0x4e, 0xdb, 0x30, | ||||||
| 	0x10, 0x8d, 0x2c, 0xcb, 0x76, 0xe6, 0x8b, 0xfd, 0xb9, 0x4b, 0x49, 0x85, 0x7e, 0xb4, 0xee, 0xe2, | 	0x14, 0xa6, 0x6d, 0x52, 0xe0, 0x8c, 0x14, 0x66, 0x4d, 0x2c, 0xca, 0xc5, 0xe8, 0x2c, 0x2e, 0xd0, | ||||||
| 	0x1f, 0xa1, 0x34, 0x32, 0x24, 0x04, 0x4a, 0x4d, 0x43, 0x20, 0x94, 0x42, 0x21, 0x21, 0x55, 0x2e, | 	0x34, 0xd2, 0x09, 0x34, 0x6d, 0x1a, 0x1a, 0x42, 0x43, 0x68, 0xd2, 0x24, 0x10, 0x4b, 0x5f, 0x60, | ||||||
| 	0x50, 0xc5, 0x1a, 0x6c, 0x93, 0x58, 0xeb, 0xac, 0xd6, 0x09, 0x3e, 0x41, 0x8f, 0xd0, 0x33, 0xf5, | 	0x21, 0xb1, 0x4a, 0x05, 0x8d, 0x8b, 0xe3, 0x80, 0xfa, 0x04, 0x7b, 0xd3, 0xbd, 0xc4, 0x6e, 0x26, | ||||||
| 	0x56, 0x65, 0x77, 0x47, 0x8a, 0x1d, 0xcb, 0xa2, 0xf9, 0xe7, 0xd1, 0xbc, 0xf7, 0x66, 0x67, 0xe6, | 	0xdb, 0x27, 0x21, 0xa1, 0x49, 0x57, 0xee, 0x72, 0xec, 0xef, 0x3b, 0xc7, 0xe7, 0xef, 0x0b, 0x38, | ||||||
| 	0x8d, 0xe1, 0x64, 0x3c, 0x55, 0x93, 0xc5, 0x4d, 0x38, 0x12, 0xb3, 0xc1, 0x6c, 0x3a, 0x92, 0x62, | 	0x09, 0x93, 0x0f, 0x5c, 0xdc, 0xf8, 0x53, 0xc1, 0x25, 0x27, 0x5b, 0x23, 0xee, 0x4f, 0xc6, 0x91, | ||||||
| 	0x30, 0x16, 0x87, 0xf6, 0x47, 0x8a, 0xea, 0x51, 0xc8, 0xdb, 0xc1, 0x5c, 0x0a, 0x55, 0x44, 0xa1, | 	0xe0, 0x3e, 0x9e, 0x7b, 0x47, 0xa3, 0xb1, 0xbc, 0xce, 0xae, 0xfc, 0x88, 0x4f, 0x06, 0xfa, 0x66, | ||||||
| 	0x89, 0x58, 0x77, 0x2c, 0x42, 0x83, 0x0a, 0xe9, 0x7b, 0x30, 0xdc, 0x2e, 0x24, 0xc5, 0x42, 0xa1, | 	0x30, 0xe2, 0xfb, 0xe6, 0x43, 0xf0, 0x4c, 0x32, 0x31, 0x48, 0x99, 0xb8, 0x1f, 0x47, 0x6c, 0xa0, | ||||||
| 	0x1c, 0x64, 0x28, 0x1f, 0xa6, 0x23, 0x24, 0x3d, 0xfb, 0xd1, 0xca, 0xf1, 0x5f, 0x0e, 0x78, 0x3f, | 	0x3d, 0xe0, 0xa1, 0x71, 0x47, 0x7f, 0xb7, 0xc0, 0xfe, 0x99, 0x31, 0x31, 0x23, 0x2e, 0xac, 0x22, | ||||||
| 	0x16, 0x28, 0x97, 0xcc, 0x87, 0x26, 0xe1, 0x7c, 0xa7, 0xe7, 0x1c, 0xec, 0x46, 0x79, 0xa8, 0x33, | 	0xce, 0x6d, 0xf5, 0x5b, 0x7b, 0xeb, 0x41, 0x6e, 0xaa, 0x9b, 0x30, 0x8e, 0x05, 0x4b, 0x53, 0xb7, | ||||||
| 	0x71, 0x92, 0x48, 0xcc, 0x32, 0xbf, 0x66, 0x33, 0x14, 0xea, 0xcc, 0x38, 0x56, 0xf8, 0x18, 0x2f, | 	0x6d, 0x6e, 0xd0, 0x54, 0x37, 0xa3, 0x50, 0xb2, 0x87, 0x70, 0xe6, 0x76, 0xcc, 0x0d, 0x9a, 0x64, | ||||||
| 	0x7d, 0xd7, 0x66, 0x28, 0x64, 0xfb, 0xd0, 0xb0, 0x75, 0xfc, 0xba, 0x49, 0x50, 0xa4, 0x19, 0xf4, | 	0x1b, 0xba, 0x26, 0x8e, 0x6b, 0xe9, 0x0b, 0xb4, 0x14, 0x03, 0xdf, 0xed, 0xda, 0x86, 0x81, 0x26, | ||||||
| 	0x6e, 0xdf, 0xb3, 0x0c, 0x0a, 0xf9, 0x29, 0x74, 0xce, 0x45, 0x9a, 0xe2, 0x48, 0x45, 0x78, 0xbf, | 	0x3d, 0x86, 0xde, 0x29, 0x4f, 0x12, 0x16, 0xc9, 0x80, 0xdd, 0x65, 0x2c, 0x95, 0xe4, 0x3d, 0xd8, | ||||||
| 	0xc0, 0x4c, 0xb1, 0x8f, 0xe0, 0xa5, 0x22, 0xc1, 0xcc, 0x77, 0x7a, 0xee, 0xc1, 0x7f, 0x47, 0xfb, | 	0x09, 0x8f, 0x59, 0xea, 0xb6, 0xfa, 0x9d, 0xbd, 0x17, 0x07, 0xdb, 0xfe, 0xd3, 0xd4, 0xfd, 0x0b, | ||||||
| 	0xe1, 0xf3, 0xd6, 0xc3, 0x4b, 0x91, 0x60, 0x64, 0x41, 0xfc, 0x15, 0xfc, 0x5f, 0xf0, 0xb3, 0xb9, | 	0x1e, 0xb3, 0xc0, 0x80, 0xe8, 0x4b, 0xd8, 0x2c, 0xf8, 0xe9, 0x94, 0x27, 0x29, 0xa3, 0xbb, 0xb0, | ||||||
| 	0x48, 0x33, 0xe4, 0x7d, 0xd8, 0xd3, 0x88, 0x2c, 0x17, 0x7c, 0x0d, 0x5e, 0x82, 0x73, 0x35, 0x31, | 	0xa1, 0x10, 0x69, 0xee, 0xf0, 0x15, 0xd8, 0x31, 0x9b, 0xca, 0x6b, 0x9d, 0xa0, 0x13, 0x18, 0x83, | ||||||
| 	0x0d, 0xb6, 0x23, 0x1b, 0xf0, 0x2f, 0xd0, 0x26, 0x94, 0xa5, 0xbd, 0xb0, 0x6e, 0x1f, 0xf6, 0xbe, | 	0x7e, 0x05, 0x07, 0x51, 0x86, 0xf6, 0xcc, 0xb8, 0xbb, 0xb0, 0xf1, 0x5d, 0x84, 0xd3, 0xeb, 0xc5, | ||||||
| 	0xc9, 0x78, 0x3e, 0xa9, 0x2e, 0x32, 0x84, 0x36, 0xa1, 0xa8, 0xc8, 0x07, 0xa8, 0x4b, 0x21, 0x94, | 	0x41, 0x8e, 0xc0, 0x41, 0x14, 0x06, 0x79, 0x07, 0x96, 0xe0, 0x5c, 0x6a, 0x54, 0x6d, 0x8c, 0x4b, | ||||||
| 	0x41, 0x95, 0xd6, 0xb8, 0x42, 0x94, 0x91, 0xc1, 0xf0, 0x53, 0x68, 0x47, 0x7a, 0x7c, 0x45, 0x23, | 	0xc6, 0x44, 0xa0, 0x31, 0xf4, 0x18, 0x9c, 0x40, 0x95, 0xaf, 0x48, 0x64, 0x1f, 0xec, 0x3b, 0xd5, | ||||||
| 	0x87, 0xe0, 0xdd, 0xeb, 0xa5, 0x11, 0xfb, 0xcd, 0x26, 0xdb, 0xec, 0x34, 0xb2, 0x28, 0x7e, 0x06, | 	0x34, 0x64, 0xbf, 0x9e, 0x67, 0xeb, 0x9e, 0x06, 0x06, 0x45, 0x4f, 0xa0, 0x97, 0xf3, 0x31, 0xba, | ||||||
| 	0x9d, 0x9c, 0x4f, 0xd5, 0x43, 0x5a, 0x4f, 0x49, 0x8f, 0x64, 0x0f, 0x43, 0xa0, 0xb5, 0x99, 0xe1, | 	0x8f, 0xed, 0xa9, 0xc9, 0x11, 0xc7, 0x43, 0x13, 0xb0, 0x6d, 0xba, 0xb8, 0x43, 0x33, 0x0d, 0xf9, | ||||||
| 	0x5e, 0x5b, 0x37, 0xe4, 0x6f, 0xe0, 0x21, 0x74, 0x9f, 0x3e, 0x91, 0x6c, 0x00, 0x2d, 0x32, 0x8d, | 	0x1b, 0xa8, 0x0f, 0x5b, 0x8f, 0x47, 0xe8, 0xd6, 0x83, 0x35, 0x1c, 0x1a, 0xe3, 0x78, 0x3d, 0x28, | ||||||
| 	0x15, 0xde, 0x8d, 0x8a, 0x98, 0xff, 0x71, 0xa0, 0xae, 0xe7, 0xc6, 0x3a, 0x50, 0x9b, 0x26, 0xe4, | 	0x6c, 0xba, 0x09, 0xce, 0x50, 0x86, 0x32, 0x2b, 0x1c, 0x7c, 0x83, 0x5e, 0x7e, 0x80, 0xf4, 0x0f, | ||||||
| 	0xb1, 0xda, 0x34, 0xa9, 0xb6, 0x57, 0x6e, 0x16, 0x77, 0xcd, 0x2c, 0xec, 0x0c, 0x5a, 0x33, 0x54, | 	0xd0, 0x4d, 0xf5, 0x09, 0xe6, 0xe5, 0xce, 0xe7, 0x85, 0x0c, 0xc4, 0xd1, 0x01, 0xd8, 0x67, 0x42, | ||||||
| 	0x71, 0x12, 0xab, 0xd8, 0xaf, 0x9b, 0x0e, 0xfa, 0xe5, 0x5b, 0x0a, 0x2f, 0x08, 0xf6, 0x35, 0x55, | 	0x70, 0xa1, 0xaa, 0x1e, 0xf1, 0x2c, 0x91, 0x79, 0xd5, 0xb5, 0x41, 0xb6, 0xa0, 0x33, 0x49, 0x47, | ||||||
| 	0x72, 0x19, 0x15, 0xac, 0x60, 0x08, 0xed, 0xb5, 0x14, 0xeb, 0x82, 0x7b, 0x8b, 0x4b, 0x7a, 0x97, | 	0x38, 0xb5, 0xea, 0x93, 0x7e, 0x82, 0xae, 0x71, 0xa1, 0x6a, 0xc8, 0x14, 0xb5, 0xb9, 0x86, 0xda, | ||||||
| 	0xfe, 0xa9, 0x37, 0xf9, 0x10, 0xdf, 0x2d, 0x90, 0x9e, 0x65, 0x83, 0xcf, 0xb5, 0x4f, 0x0e, 0x3f, | 	0x73, 0x60, 0x50, 0xf4, 0x6f, 0x0b, 0x2c, 0xd5, 0x76, 0xd2, 0x83, 0xf6, 0x38, 0xc6, 0x15, 0x69, | ||||||
| 	0x81, 0x26, 0x79, 0x4d, 0xef, 0x51, 0xfb, 0x60, 0xfb, 0x1e, 0x8d, 0x57, 0x0c, 0x86, 0x1f, 0x83, | 	0x8f, 0xe3, 0xc5, 0xdb, 0x91, 0xcf, 0x7a, 0xa7, 0x32, 0xeb, 0xe4, 0x04, 0xd6, 0x26, 0x4c, 0x86, | ||||||
| 	0x77, 0x7e, 0x27, 0xec, 0xf2, 0xff, 0x99, 0xf4, 0x13, 0xea, 0xda, 0x0a, 0x2f, 0xe1, 0x68, 0x07, | 	0x71, 0x28, 0x43, 0xd7, 0xd2, 0x0d, 0xd8, 0xad, 0x1f, 0x32, 0xff, 0x1c, 0x61, 0x67, 0x89, 0x14, | ||||||
| 	0xcf, 0x11, 0xa5, 0x1e, 0xa8, 0x5b, 0xe1, 0x2e, 0x0b, 0x3a, 0xfa, 0xed, 0x42, 0xf3, 0x92, 0x06, | 	0xb3, 0xa0, 0x60, 0x95, 0x4a, 0x65, 0x2f, 0x57, 0x2a, 0xef, 0x08, 0x9c, 0x8a, 0x33, 0x55, 0x9c, | ||||||
| 	0x7b, 0xf5, 0xd4, 0x59, 0x6f, 0x93, 0xb5, 0x7e, 0xa0, 0xc1, 0xfb, 0x0a, 0x04, 0x9d, 0xe0, 0x0e, | 	0x1b, 0x36, 0xc3, 0x4c, 0xd4, 0xa7, 0x2a, 0xe2, 0x7d, 0x78, 0x9b, 0x31, 0x4c, 0xc4, 0x18, 0x5f, | ||||||
| 	0xfb, 0x0e, 0x9e, 0x71, 0x3e, 0x7b, 0xbb, 0x89, 0x5e, 0x3d, 0x9c, 0xe0, 0xdd, 0xd6, 0xfc, 0xaa, | 	0xda, 0x9f, 0x5b, 0xf4, 0x23, 0xac, 0xe2, 0x72, 0xa9, 0xc1, 0x55, 0x83, 0xdf, 0x3c, 0xb8, 0x7a, | ||||||
| 	0x96, 0x39, 0xd5, 0x32, 0xad, 0xd5, 0x4b, 0x2f, 0xd3, 0x5a, 0xbb, 0x71, 0xbe, 0xc3, 0x2e, 0xa0, | 	0x39, 0x34, 0x86, 0x1e, 0x82, 0x7d, 0x7a, 0xcb, 0xcd, 0xb4, 0x2f, 0x4d, 0xfa, 0x05, 0x96, 0x9a, | ||||||
| 	0x61, 0x8f, 0x82, 0x95, 0x80, 0xd7, 0xce, 0x2d, 0xe8, 0x6d, 0x07, 0x14, 0x72, 0xd7, 0xd0, 0xca, | 	0xfd, 0xe7, 0x70, 0xd4, 0xca, 0x4e, 0x19, 0x13, 0xaa, 0x05, 0x9d, 0x05, 0xeb, 0x64, 0x40, 0xf4, | ||||||
| 	0xcf, 0x81, 0x95, 0xcc, 0xe5, 0xd9, 0xf5, 0x04, 0xbc, 0x0a, 0x92, 0x8b, 0xde, 0x34, 0xcc, 0x9f, | 	0x0a, 0xac, 0xe1, 0x2c, 0x89, 0x54, 0x04, 0x75, 0xf0, 0xbf, 0x1d, 0x54, 0x98, 0xd2, 0xc6, 0xb4, | ||||||
| 	0xf4, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x5b, 0x0a, 0x25, 0x2c, 0x06, 0x00, 0x00, | 	0x97, 0xd9, 0x98, 0x83, 0x3f, 0x1d, 0x58, 0xbd, 0xc0, 0x76, 0x5f, 0x3e, 0x56, 0xaf, 0x3f, 0x1f, | ||||||
|  | 	0xa4, 0xaa, 0x7a, 0xde, 0xdb, 0x05, 0x08, 0xd4, 0xb5, 0x15, 0xf2, 0x03, 0x6c, 0x2d, 0x27, 0xe4, | ||||||
|  | 	0xcd, 0x3c, 0xba, 0xac, 0x46, 0xde, 0x4e, 0xe3, 0x7d, 0xd9, 0x97, 0xd6, 0xbf, 0x3a, 0x5f, 0x65, | ||||||
|  | 	0xf9, 0xac, 0xf3, 0x55, 0x11, 0x4e, 0xba, 0x42, 0xce, 0xa1, 0x6b, 0x94, 0x86, 0xd4, 0x80, 0x2b, | ||||||
|  | 	0x1a, 0xe6, 0xf5, 0x9b, 0x01, 0x85, 0xbb, 0x21, 0xac, 0xe5, 0x1a, 0x43, 0x6a, 0xea, 0xf2, 0x44, | ||||||
|  | 	0x92, 0x3c, 0xba, 0x08, 0x52, 0x7e, 0x23, 0x4a, 0xc0, 0x4e, 0xe3, 0xd2, 0x34, 0xbf, 0xb1, 0x2a, | ||||||
|  | 	0x59, 0x74, 0xe5, 0xaa, 0xab, 0x7f, 0xa4, 0x87, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x11, 0x45, | ||||||
|  | 	0xe6, 0xf4, 0xa8, 0x07, 0x00, 0x00, | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| // Code generated by protoc-gen-micro. DO NOT EDIT. | // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||||
| // source: github.com/micro/go-micro/network/proto/network.proto | // source: network.proto | ||||||
|  |  | ||||||
| package go_micro_network | package go_micro_network | ||||||
|  |  | ||||||
| @@ -45,6 +45,8 @@ type NetworkService interface { | |||||||
| 	Routes(ctx context.Context, in *RoutesRequest, opts ...client.CallOption) (*RoutesResponse, error) | 	Routes(ctx context.Context, in *RoutesRequest, opts ...client.CallOption) (*RoutesResponse, error) | ||||||
| 	// Returns a list of known services based on routes | 	// Returns a list of known services based on routes | ||||||
| 	Services(ctx context.Context, in *ServicesRequest, opts ...client.CallOption) (*ServicesResponse, error) | 	Services(ctx context.Context, in *ServicesRequest, opts ...client.CallOption) (*ServicesResponse, error) | ||||||
|  | 	// Status returns network status | ||||||
|  | 	Status(ctx context.Context, in *StatusRequest, opts ...client.CallOption) (*StatusResponse, error) | ||||||
| } | } | ||||||
|  |  | ||||||
| type networkService struct { | type networkService struct { | ||||||
| @@ -115,6 +117,16 @@ func (c *networkService) Services(ctx context.Context, in *ServicesRequest, opts | |||||||
| 	return out, nil | 	return out, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *networkService) Status(ctx context.Context, in *StatusRequest, opts ...client.CallOption) (*StatusResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Network.Status", in) | ||||||
|  | 	out := new(StatusResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Server API for Network service | // Server API for Network service | ||||||
|  |  | ||||||
| type NetworkHandler interface { | type NetworkHandler interface { | ||||||
| @@ -128,6 +140,8 @@ type NetworkHandler interface { | |||||||
| 	Routes(context.Context, *RoutesRequest, *RoutesResponse) error | 	Routes(context.Context, *RoutesRequest, *RoutesResponse) error | ||||||
| 	// Returns a list of known services based on routes | 	// Returns a list of known services based on routes | ||||||
| 	Services(context.Context, *ServicesRequest, *ServicesResponse) error | 	Services(context.Context, *ServicesRequest, *ServicesResponse) error | ||||||
|  | 	// Status returns network status | ||||||
|  | 	Status(context.Context, *StatusRequest, *StatusResponse) error | ||||||
| } | } | ||||||
|  |  | ||||||
| func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server.HandlerOption) error { | func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server.HandlerOption) error { | ||||||
| @@ -137,6 +151,7 @@ func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server | |||||||
| 		Nodes(ctx context.Context, in *NodesRequest, out *NodesResponse) error | 		Nodes(ctx context.Context, in *NodesRequest, out *NodesResponse) error | ||||||
| 		Routes(ctx context.Context, in *RoutesRequest, out *RoutesResponse) error | 		Routes(ctx context.Context, in *RoutesRequest, out *RoutesResponse) error | ||||||
| 		Services(ctx context.Context, in *ServicesRequest, out *ServicesResponse) error | 		Services(ctx context.Context, in *ServicesRequest, out *ServicesResponse) error | ||||||
|  | 		Status(ctx context.Context, in *StatusRequest, out *StatusResponse) error | ||||||
| 	} | 	} | ||||||
| 	type Network struct { | 	type Network struct { | ||||||
| 		network | 		network | ||||||
| @@ -168,3 +183,7 @@ func (h *networkHandler) Routes(ctx context.Context, in *RoutesRequest, out *Rou | |||||||
| func (h *networkHandler) Services(ctx context.Context, in *ServicesRequest, out *ServicesResponse) error { | func (h *networkHandler) Services(ctx context.Context, in *ServicesRequest, out *ServicesResponse) error { | ||||||
| 	return h.NetworkHandler.Services(ctx, in, out) | 	return h.NetworkHandler.Services(ctx, in, out) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (h *networkHandler) Status(ctx context.Context, in *StatusRequest, out *StatusResponse) error { | ||||||
|  | 	return h.NetworkHandler.Status(ctx, in, out) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -6,16 +6,18 @@ import "github.com/micro/go-micro/router/service/proto/router.proto"; | |||||||
|  |  | ||||||
| // Network service is usesd to gain visibility into networks | // Network service is usesd to gain visibility into networks | ||||||
| service Network { | service Network { | ||||||
| 	// Connect to the network |         // Connect to the network | ||||||
| 	rpc Connect(ConnectRequest) returns (ConnectResponse) {}; |         rpc Connect(ConnectRequest) returns (ConnectResponse) {}; | ||||||
| 	// Returns the entire network graph |         // Returns the entire network graph | ||||||
| 	rpc Graph(GraphRequest) returns (GraphResponse) {}; |         rpc Graph(GraphRequest) returns (GraphResponse) {}; | ||||||
| 	// Returns a list of known nodes in the network |         // Returns a list of known nodes in the network | ||||||
|         rpc Nodes(NodesRequest) returns (NodesResponse) {}; |         rpc Nodes(NodesRequest) returns (NodesResponse) {}; | ||||||
| 	// Returns a list of known routes in the network |         // Returns a list of known routes in the network | ||||||
|         rpc Routes(RoutesRequest) returns (RoutesResponse) {}; |         rpc Routes(RoutesRequest) returns (RoutesResponse) {}; | ||||||
| 	// Returns a list of known services based on routes |         // Returns a list of known services based on routes | ||||||
| 	rpc Services(ServicesRequest) returns (ServicesResponse) {}; |         rpc Services(ServicesRequest) returns (ServicesResponse) {}; | ||||||
|  |         // Status returns network status | ||||||
|  |         rpc Status(StatusRequest) returns (StatusResponse) {}; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Query is passed in a LookupRequest | // Query is passed in a LookupRequest | ||||||
| @@ -69,6 +71,23 @@ message ServicesResponse { | |||||||
| 	repeated string services = 1; | 	repeated string services = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | message StatusRequest {} | ||||||
|  |  | ||||||
|  | message StatusResponse { | ||||||
|  |         Status status = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Error tracks network errors | ||||||
|  | message Error { | ||||||
|  |         uint32 count = 1; | ||||||
|  |         string msg = 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Status is node status | ||||||
|  | message Status { | ||||||
|  |         Error error = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
| // Node is network node | // Node is network node | ||||||
| message Node { | message Node { | ||||||
|         // node id |         // node id | ||||||
| @@ -79,6 +98,8 @@ message Node { | |||||||
|         string network = 3; |         string network = 3; | ||||||
|         // associated metadata |         // associated metadata | ||||||
|         map<string,string> metadata = 4; |         map<string,string> metadata = 4; | ||||||
|  |         // node status | ||||||
|  |         Status status = 5; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Connect is sent when the node connects to the network | // Connect is sent when the node connects to the network | ||||||
| @@ -100,3 +121,11 @@ message Peer { | |||||||
|         // node peers |         // node peers | ||||||
|         repeated Peer peers = 2; |         repeated Peer peers = 2; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Sync is network sync message | ||||||
|  | message Sync { | ||||||
|  |         // peer origin | ||||||
|  |         Peer peer = 1; | ||||||
|  |         // node routes | ||||||
|  |         repeated go.micro.router.Route routes = 2; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -384,7 +384,7 @@ func (t *tun) process() { | |||||||
| 				// if the link is not connected skip it | 				// if the link is not connected skip it | ||||||
| 				if !connected { | 				if !connected { | ||||||
| 					log.Debugf("Link for node %s not connected", id) | 					log.Debugf("Link for node %s not connected", id) | ||||||
| 					err = errors.New("link not connected") | 					err = ErrLinkDisconnected | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -392,14 +392,14 @@ func (t *tun) process() { | |||||||
| 				// and the message is being sent outbound via | 				// and the message is being sent outbound via | ||||||
| 				// a dialled connection don't use this link | 				// a dialled connection don't use this link | ||||||
| 				if loopback && msg.outbound { | 				if loopback && msg.outbound { | ||||||
| 					err = errors.New("link is loopback") | 					err = ErrLinkLoopback | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// if the message was being returned by the loopback listener | 				// if the message was being returned by the loopback listener | ||||||
| 				// send it back up the loopback link only | 				// send it back up the loopback link only | ||||||
| 				if msg.loopback && !loopback { | 				if msg.loopback && !loopback { | ||||||
| 					err = errors.New("link is not loopback") | 					err = ErrLinkRemote | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -414,7 +414,7 @@ func (t *tun) process() { | |||||||
| 					// this is where we explicitly set the link | 					// this is where we explicitly set the link | ||||||
| 					// in a message received via the listen method | 					// in a message received via the listen method | ||||||
| 					if len(msg.link) > 0 && id != msg.link { | 					if len(msg.link) > 0 && id != msg.link { | ||||||
| 						err = errors.New("link not found") | 						err = ErrLinkNotFound | ||||||
| 						continue | 						continue | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -26,6 +26,12 @@ var ( | |||||||
| 	ErrDiscoverChan = errors.New("failed to discover channel") | 	ErrDiscoverChan = errors.New("failed to discover channel") | ||||||
| 	// ErrLinkNotFound is returned when a link is specified at dial time and does not exist | 	// ErrLinkNotFound is returned when a link is specified at dial time and does not exist | ||||||
| 	ErrLinkNotFound = errors.New("link not found") | 	ErrLinkNotFound = errors.New("link not found") | ||||||
|  | 	// ErrLinkDisconnected is returned when a link we attempt to send to is disconnected | ||||||
|  | 	ErrLinkDisconnected = errors.New("link not connected") | ||||||
|  | 	// ErrLinkLoppback is returned when attempting to send an outbound message over loopback link | ||||||
|  | 	ErrLinkLoopback = errors.New("link is loopback") | ||||||
|  | 	// ErrLinkRemote is returned when attempting to send a loopback message over remote link | ||||||
|  | 	ErrLinkRemote = errors.New("link is remote") | ||||||
| 	// ErrReadTimeout is a timeout on session.Recv | 	// ErrReadTimeout is a timeout on session.Recv | ||||||
| 	ErrReadTimeout = errors.New("read timeout") | 	ErrReadTimeout = errors.New("read timeout") | ||||||
| 	// ErrDecryptingData is for when theres a nonce error | 	// ErrDecryptingData is for when theres a nonce error | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								util/proto/proto.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								util/proto/proto.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | // Package proto contains utility functions for working with protobufs | ||||||
|  | package proto | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/router" | ||||||
|  | 	pbRtr "github.com/micro/go-micro/router/service/proto" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // RouteToProto encodes route into protobuf and returns it | ||||||
|  | func RouteToProto(route router.Route) *pbRtr.Route { | ||||||
|  | 	return &pbRtr.Route{ | ||||||
|  | 		Service: route.Service, | ||||||
|  | 		Address: route.Address, | ||||||
|  | 		Gateway: route.Gateway, | ||||||
|  | 		Network: route.Network, | ||||||
|  | 		Router:  route.Router, | ||||||
|  | 		Link:    route.Link, | ||||||
|  | 		Metric:  int64(route.Metric), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ProtoToRoute decodes protobuf route into router route and returns it | ||||||
|  | func ProtoToRoute(route *pbRtr.Route) router.Route { | ||||||
|  | 	return router.Route{ | ||||||
|  | 		Service: route.Service, | ||||||
|  | 		Address: route.Address, | ||||||
|  | 		Gateway: route.Gateway, | ||||||
|  | 		Network: route.Network, | ||||||
|  | 		Router:  route.Router, | ||||||
|  | 		Link:    route.Link, | ||||||
|  | 		Metric:  route.Metric, | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user