Merge branch 'master' of github.com:micro/go-micro
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,7 @@ | |||||||
|  | # Develop tools | ||||||
|  | /.vscode/ | ||||||
|  | /.idea/ | ||||||
|  |  | ||||||
| # Binaries for programs and plugins | # Binaries for programs and plugins | ||||||
| *.exe | *.exe | ||||||
| *.exe~ | *.exe~ | ||||||
|   | |||||||
| @@ -32,5 +32,5 @@ Go Micro把分布式系统的各种细节抽象出来。下面是它的主要特 | |||||||
|  |  | ||||||
| ## 快速上手 | ## 快速上手 | ||||||
|  |  | ||||||
| 更多关于架构、安装的资料可以查看[文档](https://micro.mu/docs/go-micro_cn.html)。 | 更多关于架构、安装的资料可以查看[文档](https://micro.mu/docs/cn/)。 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ var ( | |||||||
| 		"application/proto":        protoCodec{}, | 		"application/proto":        protoCodec{}, | ||||||
| 		"application/protobuf":     protoCodec{}, | 		"application/protobuf":     protoCodec{}, | ||||||
| 		"application/octet-stream": protoCodec{}, | 		"application/octet-stream": protoCodec{}, | ||||||
|  | 		"application/grpc":         protoCodec{}, | ||||||
| 		"application/grpc+json":    jsonCodec{}, | 		"application/grpc+json":    jsonCodec{}, | ||||||
| 		"application/grpc+proto":   protoCodec{}, | 		"application/grpc+proto":   protoCodec{}, | ||||||
| 		"application/grpc+bytes":   bytesCodec{}, | 		"application/grpc+bytes":   bytesCodec{}, | ||||||
|   | |||||||
| @@ -96,7 +96,15 @@ func (r *rpcClient) call(ctx context.Context, node *registry.Node, req Request, | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c, err := r.pool.Get(address, transport.WithTimeout(opts.DialTimeout)) | 	dOpts := []transport.DialOption{ | ||||||
|  | 		transport.WithStream(), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if opts.DialTimeout >= 0 { | ||||||
|  | 		dOpts = append(dOpts, transport.WithTimeout(opts.DialTimeout)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c, err := r.pool.Get(address, dOpts...) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.InternalServerError("go.micro.client", "connection error: %v", err) | 		return errors.InternalServerError("go.micro.client", "connection error: %v", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -44,6 +44,6 @@ Load the source into config | |||||||
| // Create new config | // Create new config | ||||||
| conf := config.NewConfig() | conf := config.NewConfig() | ||||||
|  |  | ||||||
| // Load file source | // Load consul source | ||||||
| conf.Load(consulSource) | conf.Load(consulSource) | ||||||
| ``` | ``` | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								config/source/env/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								config/source/env/README.md
									
									
									
									
										vendored
									
									
								
							| @@ -91,6 +91,6 @@ Load the source into config | |||||||
| // Create new config | // Create new config | ||||||
| conf := config.NewConfig() | conf := config.NewConfig() | ||||||
|  |  | ||||||
| // Load file source | // Load env source | ||||||
| conf.Load(src) | conf.Load(src) | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -42,6 +42,6 @@ Load the source into config | |||||||
| // Create new config | // Create new config | ||||||
| conf := config.NewConfig() | conf := config.NewConfig() | ||||||
|  |  | ||||||
| // Load file source | // Load flag source | ||||||
| conf.Load(flagSource) | conf.Load(flagSource) | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -39,6 +39,6 @@ Load the source into config | |||||||
| // Create new config | // Create new config | ||||||
| conf := config.NewConfig() | conf := config.NewConfig() | ||||||
|  |  | ||||||
| // Load file source | // Load memory source | ||||||
| conf.Load(memorySource) | conf.Load(memorySource) | ||||||
| ``` | ``` | ||||||
|   | |||||||
							
								
								
									
										1005
									
								
								network/default.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1005
									
								
								network/default.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										111
									
								
								network/handler/handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								network/handler/handler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | // Package handler implements network RPC handler | ||||||
|  | package handler | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"sort" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/errors" | ||||||
|  | 	"github.com/micro/go-micro/network" | ||||||
|  | 	pbNet "github.com/micro/go-micro/network/proto" | ||||||
|  | 	pbRtr "github.com/micro/go-micro/router/proto" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Network implements network handler | ||||||
|  | type Network struct { | ||||||
|  | 	Network network.Network | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListRoutes returns a list of routing table routes | ||||||
|  | func (n *Network) ListRoutes(ctx context.Context, req *pbRtr.Request, resp *pbRtr.ListResponse) error { | ||||||
|  | 	routes, err := n.Network.Options().Router.Table().List() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var respRoutes []*pbRtr.Route | ||||||
|  | 	for _, route := range routes { | ||||||
|  | 		respRoute := &pbRtr.Route{ | ||||||
|  | 			Service: route.Service, | ||||||
|  | 			Address: route.Address, | ||||||
|  | 			Gateway: route.Gateway, | ||||||
|  | 			Network: route.Network, | ||||||
|  | 			Router:  route.Router, | ||||||
|  | 			Link:    route.Link, | ||||||
|  | 			Metric:  int64(route.Metric), | ||||||
|  | 		} | ||||||
|  | 		respRoutes = append(respRoutes, respRoute) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp.Routes = respRoutes | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListNodes returns a list of all accessible nodes in the network | ||||||
|  | func (n *Network) ListNodes(ctx context.Context, req *pbNet.ListRequest, resp *pbNet.ListResponse) error { | ||||||
|  | 	nodes := n.Network.Nodes() | ||||||
|  |  | ||||||
|  | 	var respNodes []*pbNet.Node | ||||||
|  | 	for _, node := range nodes { | ||||||
|  | 		respNode := &pbNet.Node{ | ||||||
|  | 			Id:      node.Id(), | ||||||
|  | 			Address: node.Address(), | ||||||
|  | 		} | ||||||
|  | 		respNodes = append(respNodes, respNode) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp.Nodes = respNodes | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Neighbourhood returns a list of immediate neighbours | ||||||
|  | func (n *Network) Neighbourhood(ctx context.Context, req *pbNet.NeighbourhoodRequest, resp *pbNet.NeighbourhoodResponse) error { | ||||||
|  | 	// extract the id of the node to query | ||||||
|  | 	id := req.Id | ||||||
|  | 	// if no id is passed, we assume local node | ||||||
|  | 	if id == "" { | ||||||
|  | 		id = n.Network.Id() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// get all the nodes in the network | ||||||
|  | 	nodes := n.Network.Nodes() | ||||||
|  |  | ||||||
|  | 	// sort the slice of nodes | ||||||
|  | 	sort.Slice(nodes, func(i, j int) bool { return nodes[i].Id() <= nodes[j].Id() }) | ||||||
|  | 	// find a node with a given id | ||||||
|  | 	i := sort.Search(len(nodes), func(j int) bool { return nodes[j].Id() >= id }) | ||||||
|  |  | ||||||
|  | 	var neighbours []*pbNet.Node | ||||||
|  | 	// collect all the nodes in the neighbourhood of the found node | ||||||
|  | 	if i < len(nodes) && nodes[i].Id() == id { | ||||||
|  | 		for _, neighbour := range nodes[i].Neighbourhood() { | ||||||
|  | 			// don't return yourself in response | ||||||
|  | 			if neighbour.Id() == n.Network.Id() { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			pbNeighbour := &pbNet.Node{ | ||||||
|  | 				Id:      neighbour.Id(), | ||||||
|  | 				Address: neighbour.Address(), | ||||||
|  | 			} | ||||||
|  | 			neighbours = append(neighbours, pbNeighbour) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// requested neighbourhood node | ||||||
|  | 	node := &pbNet.Node{ | ||||||
|  | 		Id:      nodes[i].Id(), | ||||||
|  | 		Address: nodes[i].Address(), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// creaate neighbourhood answer | ||||||
|  | 	neighbourhood := &pbNet.Neighbour{ | ||||||
|  | 		Node:       node, | ||||||
|  | 		Neighbours: neighbours, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp.Neighbourhood = neighbourhood | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @@ -1,2 +1,60 @@ | |||||||
| // Package network is for creating internetworks | // Package network is for creating internetworks | ||||||
| package network | package network | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// DefaultName is default network name | ||||||
|  | 	DefaultName = "go.micro" | ||||||
|  | 	// DefaultAddress is default network address | ||||||
|  | 	DefaultAddress = ":0" | ||||||
|  | 	// ResolveTime defines time interval to periodically resolve network nodes | ||||||
|  | 	ResolveTime = 1 * time.Minute | ||||||
|  | 	// AnnounceTime defines time interval to periodically announce node neighbours | ||||||
|  | 	AnnounceTime = 30 * time.Second | ||||||
|  | 	// PruneTime defines time interval to periodically check nodes that need to be pruned | ||||||
|  | 	// due to their not announcing their presence within this time interval | ||||||
|  | 	PruneTime = 90 * time.Second | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Node is network node | ||||||
|  | type Node interface { | ||||||
|  | 	// Id is node id | ||||||
|  | 	Id() string | ||||||
|  | 	// Address is node bind address | ||||||
|  | 	Address() string | ||||||
|  | 	// Neighbourhood is node neighbourhood | ||||||
|  | 	Neighbourhood() []Node | ||||||
|  | 	// Network is the network node is in | ||||||
|  | 	Network() Network | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Network is micro network | ||||||
|  | type Network interface { | ||||||
|  | 	// Node is network node | ||||||
|  | 	Node | ||||||
|  | 	// Options returns the network options | ||||||
|  | 	Options() Options | ||||||
|  | 	// Name of the network | ||||||
|  | 	Name() string | ||||||
|  | 	// Connect starts the resolver and tunnel server | ||||||
|  | 	Connect() error | ||||||
|  | 	// Nodes returns list of network nodes | ||||||
|  | 	Nodes() []Node | ||||||
|  | 	// Close stops the tunnel and resolving | ||||||
|  | 	Close() error | ||||||
|  | 	// Client is micro client | ||||||
|  | 	Client() client.Client | ||||||
|  | 	// Server is micro server | ||||||
|  | 	Server() server.Server | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewNetwork returns a new network interface | ||||||
|  | func NewNetwork(opts ...Option) Network { | ||||||
|  | 	return newNetwork(opts...) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										103
									
								
								network/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								network/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | package network | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/google/uuid" | ||||||
|  | 	"github.com/micro/go-micro/network/resolver" | ||||||
|  | 	"github.com/micro/go-micro/network/resolver/registry" | ||||||
|  | 	"github.com/micro/go-micro/proxy" | ||||||
|  | 	"github.com/micro/go-micro/proxy/mucp" | ||||||
|  | 	"github.com/micro/go-micro/router" | ||||||
|  | 	"github.com/micro/go-micro/tunnel" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Option func(*Options) | ||||||
|  |  | ||||||
|  | // Options configure network | ||||||
|  | type Options struct { | ||||||
|  | 	// Id of the node | ||||||
|  | 	Id string | ||||||
|  | 	// Name of the network | ||||||
|  | 	Name string | ||||||
|  | 	// Address to bind to | ||||||
|  | 	Address string | ||||||
|  | 	// Nodes is a list of seed nodes | ||||||
|  | 	Nodes []string | ||||||
|  | 	// Tunnel is network tunnel | ||||||
|  | 	Tunnel tunnel.Tunnel | ||||||
|  | 	// Router is network router | ||||||
|  | 	Router router.Router | ||||||
|  | 	// Proxy is network proxy | ||||||
|  | 	Proxy proxy.Proxy | ||||||
|  | 	// Resolver is network resolver | ||||||
|  | 	Resolver resolver.Resolver | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Id sets the id of the network node | ||||||
|  | func Id(id string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Id = id | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Name sets the network name | ||||||
|  | func Name(n string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Name = n | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Address sets the network address | ||||||
|  | func Address(a string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Address = a | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Nodes is a list of seed nodes used along | ||||||
|  | // with resolved node | ||||||
|  | func Nodes(n ...string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Nodes = n | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Tunnel sets the network tunnel | ||||||
|  | func Tunnel(t tunnel.Tunnel) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Tunnel = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Router sets the network router | ||||||
|  | func Router(r router.Router) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Router = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Proxy sets the network proxy | ||||||
|  | func Proxy(p proxy.Proxy) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Proxy = p | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Resolver is the network resolver | ||||||
|  | func Resolver(r resolver.Resolver) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Resolver = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DefaultOptions returns network default options | ||||||
|  | func DefaultOptions() Options { | ||||||
|  | 	return Options{ | ||||||
|  | 		Id:       uuid.New().String(), | ||||||
|  | 		Name:     DefaultName, | ||||||
|  | 		Address:  DefaultAddress, | ||||||
|  | 		Tunnel:   tunnel.NewTunnel(), | ||||||
|  | 		Router:   router.DefaultRouter, | ||||||
|  | 		Proxy:    mucp.NewProxy(), | ||||||
|  | 		Resolver: ®istry.Resolver{}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										126
									
								
								network/proto/network.micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								network/proto/network.micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||||
|  | // source: network.proto | ||||||
|  |  | ||||||
|  | package go_micro_network | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	fmt "fmt" | ||||||
|  | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	proto1 "github.com/micro/go-micro/router/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	context "context" | ||||||
|  | 	client "github.com/micro/go-micro/client" | ||||||
|  | 	server "github.com/micro/go-micro/server" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ = proto.Marshal | ||||||
|  | var _ = fmt.Errorf | ||||||
|  | var _ = math.Inf | ||||||
|  |  | ||||||
|  | // This is a compile-time assertion to ensure that this generated file | ||||||
|  | // is compatible with the proto package it is being compiled against. | ||||||
|  | // A compilation error at this line likely means your copy of the | ||||||
|  | // proto package needs to be updated. | ||||||
|  | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ context.Context | ||||||
|  | var _ client.Option | ||||||
|  | var _ server.Option | ||||||
|  |  | ||||||
|  | // Client API for Network service | ||||||
|  |  | ||||||
|  | type NetworkService interface { | ||||||
|  | 	ListRoutes(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.ListResponse, error) | ||||||
|  | 	ListNodes(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) | ||||||
|  | 	Neighbourhood(ctx context.Context, in *NeighbourhoodRequest, opts ...client.CallOption) (*NeighbourhoodResponse, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type networkService struct { | ||||||
|  | 	c    client.Client | ||||||
|  | 	name string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewNetworkService(name string, c client.Client) NetworkService { | ||||||
|  | 	if c == nil { | ||||||
|  | 		c = client.NewClient() | ||||||
|  | 	} | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		name = "go.micro.network" | ||||||
|  | 	} | ||||||
|  | 	return &networkService{ | ||||||
|  | 		c:    c, | ||||||
|  | 		name: name, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *networkService) ListRoutes(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.ListResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Network.ListRoutes", in) | ||||||
|  | 	out := new(proto1.ListResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *networkService) ListNodes(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Network.ListNodes", in) | ||||||
|  | 	out := new(ListResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *networkService) Neighbourhood(ctx context.Context, in *NeighbourhoodRequest, opts ...client.CallOption) (*NeighbourhoodResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Network.Neighbourhood", in) | ||||||
|  | 	out := new(NeighbourhoodResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Server API for Network service | ||||||
|  |  | ||||||
|  | type NetworkHandler interface { | ||||||
|  | 	ListRoutes(context.Context, *proto1.Request, *proto1.ListResponse) error | ||||||
|  | 	ListNodes(context.Context, *ListRequest, *ListResponse) error | ||||||
|  | 	Neighbourhood(context.Context, *NeighbourhoodRequest, *NeighbourhoodResponse) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RegisterNetworkHandler(s server.Server, hdlr NetworkHandler, opts ...server.HandlerOption) error { | ||||||
|  | 	type network interface { | ||||||
|  | 		ListRoutes(ctx context.Context, in *proto1.Request, out *proto1.ListResponse) error | ||||||
|  | 		ListNodes(ctx context.Context, in *ListRequest, out *ListResponse) error | ||||||
|  | 		Neighbourhood(ctx context.Context, in *NeighbourhoodRequest, out *NeighbourhoodResponse) error | ||||||
|  | 	} | ||||||
|  | 	type Network struct { | ||||||
|  | 		network | ||||||
|  | 	} | ||||||
|  | 	h := &networkHandler{hdlr} | ||||||
|  | 	return s.Handle(s.NewHandler(&Network{h}, opts...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type networkHandler struct { | ||||||
|  | 	NetworkHandler | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *networkHandler) ListRoutes(ctx context.Context, in *proto1.Request, out *proto1.ListResponse) error { | ||||||
|  | 	return h.NetworkHandler.ListRoutes(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *networkHandler) ListNodes(ctx context.Context, in *ListRequest, out *ListResponse) error { | ||||||
|  | 	return h.NetworkHandler.ListNodes(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *networkHandler) Neighbourhood(ctx context.Context, in *NeighbourhoodRequest, out *NeighbourhoodResponse) error { | ||||||
|  | 	return h.NetworkHandler.Neighbourhood(ctx, in, out) | ||||||
|  | } | ||||||
							
								
								
									
										438
									
								
								network/proto/network.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										438
									
								
								network/proto/network.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,438 @@ | |||||||
|  | // Code generated by protoc-gen-go. DO NOT EDIT. | ||||||
|  | // source: network.proto | ||||||
|  |  | ||||||
|  | package go_micro_network | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	fmt "fmt" | ||||||
|  | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	_ "github.com/micro/go-micro/router/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ = proto.Marshal | ||||||
|  | var _ = fmt.Errorf | ||||||
|  | var _ = math.Inf | ||||||
|  |  | ||||||
|  | // This is a compile-time assertion to ensure that this generated file | ||||||
|  | // is compatible with the proto package it is being compiled against. | ||||||
|  | // A compilation error at this line likely means your copy of the | ||||||
|  | // proto package needs to be updated. | ||||||
|  | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||||
|  |  | ||||||
|  | // Empty request | ||||||
|  | type ListRequest struct { | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListRequest) Reset()         { *m = ListRequest{} } | ||||||
|  | func (m *ListRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*ListRequest) ProtoMessage()    {} | ||||||
|  | func (*ListRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{0} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ListRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ListRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_ListRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | // ListResponse is returned by ListNodes and ListNeighbours | ||||||
|  | type ListResponse struct { | ||||||
|  | 	Nodes                []*Node  `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListResponse) Reset()         { *m = ListResponse{} } | ||||||
|  | func (m *ListResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*ListResponse) ProtoMessage()    {} | ||||||
|  | func (*ListResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{1} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ListResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ListResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_ListResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *ListResponse) GetNodes() []*Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Nodes | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NeighbourhoodRequest is sent to query node neighbourhood | ||||||
|  | type NeighbourhoodRequest struct { | ||||||
|  | 	Id                   string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodRequest) Reset()         { *m = NeighbourhoodRequest{} } | ||||||
|  | func (m *NeighbourhoodRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*NeighbourhoodRequest) ProtoMessage()    {} | ||||||
|  | func (*NeighbourhoodRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{2} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_NeighbourhoodRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_NeighbourhoodRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_NeighbourhoodRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodRequest) GetId() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Id | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NeighbourhoodResponse contains node neighbourhood hierarchy | ||||||
|  | type NeighbourhoodResponse struct { | ||||||
|  | 	Neighbourhood        *Neighbour `protobuf:"bytes,1,opt,name=neighbourhood,proto3" json:"neighbourhood,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{}   `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte     `json:"-"` | ||||||
|  | 	XXX_sizecache        int32      `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodResponse) Reset()         { *m = NeighbourhoodResponse{} } | ||||||
|  | func (m *NeighbourhoodResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*NeighbourhoodResponse) ProtoMessage()    {} | ||||||
|  | func (*NeighbourhoodResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{3} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_NeighbourhoodResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_NeighbourhoodResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *NeighbourhoodResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_NeighbourhoodResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_NeighbourhoodResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *NeighbourhoodResponse) GetNeighbourhood() *Neighbour { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Neighbourhood | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Node is network node | ||||||
|  | type Node struct { | ||||||
|  | 	// node ide | ||||||
|  | 	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` | ||||||
|  | 	// node address | ||||||
|  | 	Address              string   `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) Reset()         { *m = Node{} } | ||||||
|  | func (m *Node) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Node) ProtoMessage()    {} | ||||||
|  | func (*Node) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{4} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Node.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Node.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Node.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Node.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Node.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Node proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Node) GetId() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Id | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) GetAddress() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Address | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Connect is sent when the node connects to the network | ||||||
|  | type Connect struct { | ||||||
|  | 	// network mode | ||||||
|  | 	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Connect) Reset()         { *m = Connect{} } | ||||||
|  | func (m *Connect) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Connect) ProtoMessage()    {} | ||||||
|  | func (*Connect) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{5} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Connect) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Connect.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Connect) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Connect.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Connect) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Connect.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Connect) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Connect.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Connect) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Connect.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Connect proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Connect) GetNode() *Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Node | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Close is sent when the node disconnects from the network | ||||||
|  | type Close struct { | ||||||
|  | 	// network node | ||||||
|  | 	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Close) Reset()         { *m = Close{} } | ||||||
|  | func (m *Close) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Close) ProtoMessage()    {} | ||||||
|  | func (*Close) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{6} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Close) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Close.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Close) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Close.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Close) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Close.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Close) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Close.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Close) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Close.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Close proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Close) GetNode() *Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Node | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Solicit is sent when requesting route advertisement from the network nodes | ||||||
|  | type Solicit struct { | ||||||
|  | 	// network node | ||||||
|  | 	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Solicit) Reset()         { *m = Solicit{} } | ||||||
|  | func (m *Solicit) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Solicit) ProtoMessage()    {} | ||||||
|  | func (*Solicit) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{7} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Solicit) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Solicit.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Solicit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Solicit.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Solicit) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Solicit.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Solicit) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Solicit.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Solicit) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Solicit.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Solicit proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Solicit) GetNode() *Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Node | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Neighbour is used to nnounce node neighbourhood | ||||||
|  | type Neighbour struct { | ||||||
|  | 	// network node | ||||||
|  | 	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` | ||||||
|  | 	// neighbours | ||||||
|  | 	Neighbours           []*Node  `protobuf:"bytes,3,rep,name=neighbours,proto3" json:"neighbours,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Neighbour) Reset()         { *m = Neighbour{} } | ||||||
|  | func (m *Neighbour) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Neighbour) ProtoMessage()    {} | ||||||
|  | func (*Neighbour) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_8571034d60397816, []int{8} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Neighbour) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Neighbour.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Neighbour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Neighbour.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Neighbour) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Neighbour.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Neighbour) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Neighbour.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Neighbour) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Neighbour.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Neighbour proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Neighbour) GetNode() *Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Node | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Neighbour) GetNeighbours() []*Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Neighbours | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	proto.RegisterType((*ListRequest)(nil), "go.micro.network.ListRequest") | ||||||
|  | 	proto.RegisterType((*ListResponse)(nil), "go.micro.network.ListResponse") | ||||||
|  | 	proto.RegisterType((*NeighbourhoodRequest)(nil), "go.micro.network.NeighbourhoodRequest") | ||||||
|  | 	proto.RegisterType((*NeighbourhoodResponse)(nil), "go.micro.network.NeighbourhoodResponse") | ||||||
|  | 	proto.RegisterType((*Node)(nil), "go.micro.network.Node") | ||||||
|  | 	proto.RegisterType((*Connect)(nil), "go.micro.network.Connect") | ||||||
|  | 	proto.RegisterType((*Close)(nil), "go.micro.network.Close") | ||||||
|  | 	proto.RegisterType((*Solicit)(nil), "go.micro.network.Solicit") | ||||||
|  | 	proto.RegisterType((*Neighbour)(nil), "go.micro.network.Neighbour") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func init() { proto.RegisterFile("network.proto", fileDescriptor_8571034d60397816) } | ||||||
|  |  | ||||||
|  | var fileDescriptor_8571034d60397816 = []byte{ | ||||||
|  | 	// 360 bytes of a gzipped FileDescriptorProto | ||||||
|  | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x41, 0x4f, 0xf2, 0x40, | ||||||
|  | 	0x10, 0xfd, 0x28, 0xf0, 0x35, 0x0c, 0x1f, 0x5f, 0xcc, 0x46, 0x4d, 0x53, 0x83, 0x21, 0x7b, 0x40, | ||||||
|  | 	0x62, 0xb4, 0x18, 0x08, 0x9e, 0xbc, 0x18, 0x0e, 0x5e, 0x08, 0x87, 0x7a, 0xf3, 0x66, 0xbb, 0x9b, | ||||||
|  | 	0xb2, 0x11, 0x3a, 0xb8, 0xbb, 0x8d, 0x7f, 0xc0, 0x1f, 0x6e, 0xba, 0x5d, 0xb0, 0x80, 0x60, 0xb8, | ||||||
|  | 	0x75, 0xe6, 0xbd, 0x37, 0x6f, 0xa7, 0xfb, 0x16, 0x5a, 0x29, 0xd7, 0x1f, 0x28, 0xdf, 0x82, 0xa5, | ||||||
|  | 	0x44, 0x8d, 0xe4, 0x24, 0xc1, 0x60, 0x21, 0x62, 0x89, 0x81, 0xed, 0xfb, 0xc3, 0x44, 0xe8, 0x59, | ||||||
|  | 	0x16, 0x05, 0x31, 0x2e, 0xfa, 0x06, 0xe9, 0x27, 0x78, 0x5b, 0x7c, 0x48, 0xcc, 0x34, 0x97, 0x7d, | ||||||
|  | 	0xa3, 0xb4, 0x45, 0x31, 0x86, 0xb6, 0xa0, 0x39, 0x11, 0x4a, 0x87, 0xfc, 0x3d, 0xe3, 0x4a, 0xd3, | ||||||
|  | 	0x07, 0xf8, 0x57, 0x94, 0x6a, 0x89, 0xa9, 0xe2, 0xe4, 0x06, 0xea, 0x29, 0x32, 0xae, 0xbc, 0x4a, | ||||||
|  | 	0xa7, 0xda, 0x6b, 0x0e, 0xce, 0x83, 0x6d, 0xd7, 0x60, 0x8a, 0x8c, 0x87, 0x05, 0x89, 0x76, 0xe1, | ||||||
|  | 	0x74, 0xca, 0x45, 0x32, 0x8b, 0x30, 0x93, 0x33, 0x44, 0x66, 0xa7, 0x92, 0xff, 0xe0, 0x08, 0xe6, | ||||||
|  | 	0x55, 0x3a, 0x95, 0x5e, 0x23, 0x74, 0x04, 0xa3, 0x2f, 0x70, 0xb6, 0xc5, 0xb3, 0x76, 0x8f, 0xf9, | ||||||
|  | 	0x96, 0x25, 0xc0, 0x68, 0x9a, 0x83, 0x8b, 0x1f, 0x6c, 0x57, 0xb4, 0x70, 0x53, 0x41, 0xef, 0xa0, | ||||||
|  | 	0x96, 0x1f, 0x69, 0xdb, 0x93, 0x78, 0xe0, 0xbe, 0x32, 0x26, 0xb9, 0x52, 0x9e, 0x63, 0x9a, 0xab, | ||||||
|  | 	0x92, 0x8e, 0xc0, 0x1d, 0x63, 0x9a, 0xf2, 0x58, 0x93, 0x6b, 0xa8, 0xe5, 0x9b, 0x58, 0xdb, 0x7d, | ||||||
|  | 	0xdb, 0x1a, 0x0e, 0x1d, 0x42, 0x7d, 0x3c, 0x47, 0xc5, 0x8f, 0x12, 0x8d, 0xc0, 0x7d, 0xc6, 0xb9, | ||||||
|  | 	0x88, 0xc5, 0x71, 0x5e, 0x08, 0x8d, 0xf5, 0xc2, 0xc7, 0x08, 0xc9, 0x3d, 0xc0, 0xfa, 0xf7, 0x28, | ||||||
|  | 	0xaf, 0x7a, 0xf0, 0x12, 0x4b, 0xcc, 0xc1, 0xa7, 0x03, 0xee, 0xb4, 0x00, 0xc9, 0x13, 0x80, 0xc9, | ||||||
|  | 	0x44, 0x1e, 0x1b, 0x45, 0xbc, 0x6f, 0xb5, 0x0d, 0x92, 0xbd, 0x65, 0xbf, 0xbd, 0x83, 0x94, 0xa3, | ||||||
|  | 	0x44, 0xff, 0x90, 0x09, 0x34, 0xf2, 0x4e, 0x6e, 0xa6, 0x48, 0x7b, 0xf7, 0x14, 0xa5, 0x20, 0xfa, | ||||||
|  | 	0x97, 0xfb, 0xe0, 0xf5, 0xb4, 0x08, 0x5a, 0x1b, 0x21, 0x22, 0xdd, 0x03, 0x29, 0x29, 0xa5, 0xd1, | ||||||
|  | 	0xbf, 0xfa, 0x95, 0xb7, 0xf2, 0x88, 0xfe, 0x9a, 0x47, 0x32, 0xfc, 0x0a, 0x00, 0x00, 0xff, 0xff, | ||||||
|  | 	0x59, 0xcf, 0xab, 0xb5, 0x7c, 0x03, 0x00, 0x00, | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								network/proto/network.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								network/proto/network.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | syntax = "proto3"; | ||||||
|  |  | ||||||
|  | package go.micro.network; | ||||||
|  |  | ||||||
|  | import "github.com/micro/go-micro/router/proto/router.proto"; | ||||||
|  |  | ||||||
|  | // Network service is usesd to gain visibility into networks | ||||||
|  | service Network { | ||||||
|  |         rpc ListRoutes(go.micro.router.Request) returns (go.micro.router.ListResponse) {}; | ||||||
|  |         rpc ListNodes(ListRequest) returns (ListResponse) {}; | ||||||
|  |         rpc Neighbourhood(NeighbourhoodRequest) returns (NeighbourhoodResponse) {}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Empty request | ||||||
|  | message ListRequest {} | ||||||
|  |  | ||||||
|  | // ListResponse is returned by ListNodes and ListNeighbours | ||||||
|  | message ListResponse { | ||||||
|  | 	repeated Node nodes = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NeighbourhoodRequest is sent to query node neighbourhood | ||||||
|  | message NeighbourhoodRequest { | ||||||
|  |         string id = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NeighbourhoodResponse contains node neighbourhood hierarchy | ||||||
|  | message NeighbourhoodResponse { | ||||||
|  |         Neighbour neighbourhood = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Node is network node | ||||||
|  | message Node { | ||||||
|  |         // node ide | ||||||
|  |         string id = 1; | ||||||
|  |         // node address | ||||||
|  |         string address = 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Connect is sent when the node connects to the network | ||||||
|  | message Connect { | ||||||
|  |         // network mode | ||||||
|  |         Node node = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Close is sent when the node disconnects from the network | ||||||
|  | message Close { | ||||||
|  |         // network node | ||||||
|  |         Node node = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Solicit is sent when requesting route advertisement from the network nodes | ||||||
|  | message Solicit { | ||||||
|  |         // network node | ||||||
|  |         Node node = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Neighbour is used to nnounce node neighbourhood | ||||||
|  | message Neighbour { | ||||||
|  |         // network node | ||||||
|  |         Node node = 1; | ||||||
|  |         // neighbours | ||||||
|  |         repeated Node neighbours = 3; | ||||||
|  | } | ||||||
| @@ -8,6 +8,7 @@ import ( | |||||||
| 	"github.com/micro/go-micro/network/resolver" | 	"github.com/micro/go-micro/network/resolver" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Resolver is a DNS network resolve | ||||||
| type Resolver struct{} | type Resolver struct{} | ||||||
|  |  | ||||||
| // Resolve assumes ID is a domain name e.g micro.mu | // Resolve assumes ID is a domain name e.g micro.mu | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ import ( | |||||||
| 	"github.com/micro/go-micro/network/resolver" | 	"github.com/micro/go-micro/network/resolver" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Resolver is a HTTP network resolver | ||||||
| type Resolver struct { | type Resolver struct { | ||||||
| 	// If not set, defaults to http | 	// If not set, defaults to http | ||||||
| 	Proto string | 	Proto string | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import ( | |||||||
| 	"github.com/micro/go-micro/registry" | 	"github.com/micro/go-micro/registry" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Resolver is a registry network resolver | ||||||
| type Resolver struct { | type Resolver struct { | ||||||
| 	// Registry is the registry to use otherwise we use the defaul | 	// Registry is the registry to use otherwise we use the defaul | ||||||
| 	Registry registry.Registry | 	Registry registry.Registry | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ package resolver | |||||||
| // via the name to connect to. This is done based on Network.Name(). | // via the name to connect to. This is done based on Network.Name(). | ||||||
| // Before we can be part of any network, we have to connect to it. | // Before we can be part of any network, we have to connect to it. | ||||||
| type Resolver interface { | type Resolver interface { | ||||||
| 	// Resolve returns a list of addresses for an name | 	// Resolve returns a list of addresses for a name | ||||||
| 	Resolve(name string) ([]*Record, error) | 	Resolve(name string) ([]*Record, error) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										125
									
								
								plugin/default.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								plugin/default.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | |||||||
|  | // Package plugin provides the ability to load plugins | ||||||
|  | package plugin | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	pg "plugin" | ||||||
|  | 	"strings" | ||||||
|  | 	"text/template" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/broker" | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/client/selector" | ||||||
|  | 	"github.com/micro/go-micro/config/cmd" | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | 	"github.com/micro/go-micro/transport" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type plugin struct{} | ||||||
|  |  | ||||||
|  | // Init sets up the plugin | ||||||
|  | func (p *plugin) Init(c *Config) error { | ||||||
|  | 	switch c.Type { | ||||||
|  | 	case "broker": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...broker.Option) broker.Broker) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultBrokers[c.Name] = pg | ||||||
|  | 	case "client": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...client.Option) client.Client) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultClients[c.Name] = pg | ||||||
|  | 	case "registry": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...registry.Option) registry.Registry) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultRegistries[c.Name] = pg | ||||||
|  |  | ||||||
|  | 	case "selector": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...selector.Option) selector.Selector) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultSelectors[c.Name] = pg | ||||||
|  | 	case "server": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...server.Option) server.Server) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultServers[c.Name] = pg | ||||||
|  | 	case "transport": | ||||||
|  | 		pg, ok := c.NewFunc.(func(...transport.Option) transport.Transport) | ||||||
|  | 		if !ok { | ||||||
|  | 			return fmt.Errorf("Invalid plugin %s", c.Name) | ||||||
|  | 		} | ||||||
|  | 		cmd.DefaultTransports[c.Name] = pg | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("Unknown plugin type: %s for %s", c.Type, c.Name) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Load loads a plugin created with `go build -buildmode=plugin` | ||||||
|  | func (p *plugin) Load(path string) (*Config, error) { | ||||||
|  | 	plugin, err := pg.Open(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	s, err := plugin.Lookup("Plugin") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	pl, ok := s.(*Config) | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, errors.New("could not cast Plugin object") | ||||||
|  | 	} | ||||||
|  | 	return pl, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Generate creates a go file at the specified path. | ||||||
|  | // You must use `go build -buildmode=plugin`to build it. | ||||||
|  | func (p *plugin) Generate(path string, c *Config) error { | ||||||
|  | 	f, err := os.Create(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer f.Close() | ||||||
|  | 	t, err := template.New(c.Name).Parse(tmpl) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return t.Execute(f, c) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Build generates a dso plugin using the go command `go build -buildmode=plugin` | ||||||
|  | func (p *plugin) Build(path string, c *Config) error { | ||||||
|  | 	path = strings.TrimSuffix(path, ".so") | ||||||
|  |  | ||||||
|  | 	// create go file in tmp path | ||||||
|  | 	temp := os.TempDir() | ||||||
|  | 	base := filepath.Base(path) | ||||||
|  | 	goFile := filepath.Join(temp, base+".go") | ||||||
|  |  | ||||||
|  | 	// generate .go file | ||||||
|  | 	if err := p.Generate(goFile, c); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	// remove .go file | ||||||
|  | 	defer os.Remove(goFile) | ||||||
|  |  | ||||||
|  | 	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil && !os.IsExist(err) { | ||||||
|  | 		return fmt.Errorf("Failed to create dir %s: %v", filepath.Dir(path), err) | ||||||
|  | 	} | ||||||
|  | 	cmd := exec.Command("go", "build", "-buildmode=plugin", "-o", path+".so", goFile) | ||||||
|  | 	return cmd.Run() | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								plugin/plugin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								plugin/plugin.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // Package plugin provides the ability to load plugins | ||||||
|  | package plugin | ||||||
|  |  | ||||||
|  | // Plugin is a plugin loaded from a file | ||||||
|  | type Plugin interface { | ||||||
|  | 	// Initialise a plugin with the config | ||||||
|  | 	Init(c *Config) error | ||||||
|  | 	// Load loads a .so plugin at the given path | ||||||
|  | 	Load(path string) (*Config, error) | ||||||
|  | 	// Build a .so plugin with config at the path specified | ||||||
|  | 	Build(path string, c *Config) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Config is the plugin config | ||||||
|  | type Config struct { | ||||||
|  | 	// Name of the plugin e.g rabbitmq | ||||||
|  | 	Name string | ||||||
|  | 	// Type of the plugin e.g broker | ||||||
|  | 	Type string | ||||||
|  | 	// Path specifies the import path | ||||||
|  | 	Path string | ||||||
|  | 	// NewFunc creates an instance of the plugin | ||||||
|  | 	NewFunc interface{} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// Default plugin loader | ||||||
|  | 	DefaultPlugin = NewPlugin() | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // NewPlugin creates a new plugin interface | ||||||
|  | func NewPlugin() Plugin { | ||||||
|  | 	return &plugin{} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Build(path string, c *Config) error { | ||||||
|  | 	return DefaultPlugin.Build(path, c) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Load(path string) (*Config, error) { | ||||||
|  | 	return DefaultPlugin.Load(path) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Init(c *Config) error { | ||||||
|  | 	return DefaultPlugin.Init(c) | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								plugin/template.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								plugin/template.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | package plugin | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	tmpl = ` | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/plugin" | ||||||
|  |  | ||||||
|  | 	"{{.Path}}" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var Plugin = plugin.Config{ | ||||||
|  | 	Name: "{{.Name}}", | ||||||
|  | 	Type: "{{.Type}}", | ||||||
|  | 	Path: "{{.Path}}", | ||||||
|  | 	NewFunc: {{.Name}}.{{.NewFunc}}, | ||||||
|  | } | ||||||
|  | ` | ||||||
|  | ) | ||||||
| @@ -161,9 +161,6 @@ func (p *Proxy) manageRouteCache(route router.Route, action string) error { | |||||||
| 		} | 		} | ||||||
| 		p.Routes[route.Service][route.Hash()] = route | 		p.Routes[route.Service][route.Hash()] = route | ||||||
| 	case "delete": | 	case "delete": | ||||||
| 		if _, ok := p.Routes[route.Service]; !ok { |  | ||||||
| 			return fmt.Errorf("route not found") |  | ||||||
| 		} |  | ||||||
| 		delete(p.Routes[route.Service], route.Hash()) | 		delete(p.Routes[route.Service], route.Hash()) | ||||||
| 	default: | 	default: | ||||||
| 		return fmt.Errorf("unknown action: %s", action) | 		return fmt.Errorf("unknown action: %s", action) | ||||||
| @@ -219,6 +216,10 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server | |||||||
| 	// endpoint to call | 	// endpoint to call | ||||||
| 	endpoint := req.Endpoint() | 	endpoint := req.Endpoint() | ||||||
|  |  | ||||||
|  | 	if len(service) == 0 { | ||||||
|  | 		return errors.BadRequest("go.micro.proxy", "service name is blank") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// are we network routing or local routing | 	// are we network routing or local routing | ||||||
| 	if len(p.Links) == 0 { | 	if len(p.Links) == 0 { | ||||||
| 		local = true | 		local = true | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								registry/handler/handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								registry/handler/handler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | package handler | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/errors" | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	pb "github.com/micro/go-micro/registry/proto" | ||||||
|  | 	"github.com/micro/go-micro/registry/service" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Registry struct { | ||||||
|  | 	// internal registry | ||||||
|  | 	Registry registry.Registry | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error { | ||||||
|  | 	services, err := r.Registry.GetService(req.Service) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 	} | ||||||
|  | 	for _, srv := range services { | ||||||
|  | 		rsp.Services = append(rsp.Services, service.ToProto(srv)) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { | ||||||
|  | 	err := r.Registry.Register(service.ToService(req)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Registry) Deregister(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error { | ||||||
|  | 	err := r.Registry.Deregister(service.ToService(req)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Registry) ListServices(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { | ||||||
|  | 	services, err := r.Registry.ListServices() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 	} | ||||||
|  | 	for _, srv := range services { | ||||||
|  | 		rsp.Services = append(rsp.Services, service.ToProto(srv)) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Registry) Watch(ctx context.Context, req *pb.WatchRequest, rsp pb.Registry_WatchStream) error { | ||||||
|  | 	watcher, err := r.Registry.Watch(registry.WatchService(req.Service)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		next, err := watcher.Next() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 		} | ||||||
|  | 		err = rsp.Send(&pb.Result{ | ||||||
|  | 			Action:  next.Action, | ||||||
|  | 			Service: service.ToProto(next.Service), | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return errors.InternalServerError("go.micro.registry", err.Error()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @@ -2,6 +2,8 @@ | |||||||
| package mdns | package mdns | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/registry" | 	"github.com/micro/go-micro/registry" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -9,3 +11,13 @@ import ( | |||||||
| func NewRegistry(opts ...registry.Option) registry.Registry { | func NewRegistry(opts ...registry.Option) registry.Registry { | ||||||
| 	return registry.NewRegistry(opts...) | 	return registry.NewRegistry(opts...) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Domain sets the mdnsDomain | ||||||
|  | func Domain(d string) registry.Option { | ||||||
|  | 	return func(o *registry.Options) { | ||||||
|  | 		if o.Context == nil { | ||||||
|  | 			o.Context = context.Background() | ||||||
|  | 		} | ||||||
|  | 		o.Context = context.WithValue(o.Context, "mdns.domain", d) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,6 +14,11 @@ import ( | |||||||
| 	hash "github.com/mitchellh/hashstructure" | 	hash "github.com/mitchellh/hashstructure" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// use a .micro domain rather than .local | ||||||
|  | 	mdnsDomain = "micro" | ||||||
|  | ) | ||||||
|  |  | ||||||
| type mdnsTxt struct { | type mdnsTxt struct { | ||||||
| 	Service   string | 	Service   string | ||||||
| 	Version   string | 	Version   string | ||||||
| @@ -29,6 +34,8 @@ type mdnsEntry struct { | |||||||
|  |  | ||||||
| type mdnsRegistry struct { | type mdnsRegistry struct { | ||||||
| 	opts Options | 	opts Options | ||||||
|  | 	// the mdns domain | ||||||
|  | 	domain string | ||||||
|  |  | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| 	services map[string][]*mdnsEntry | 	services map[string][]*mdnsEntry | ||||||
| @@ -36,11 +43,25 @@ type mdnsRegistry struct { | |||||||
|  |  | ||||||
| func newRegistry(opts ...Option) Registry { | func newRegistry(opts ...Option) Registry { | ||||||
| 	options := Options{ | 	options := Options{ | ||||||
|  | 		Context: context.Background(), | ||||||
| 		Timeout: time.Millisecond * 100, | 		Timeout: time.Millisecond * 100, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// set the domain | ||||||
|  | 	domain := mdnsDomain | ||||||
|  |  | ||||||
|  | 	d, ok := options.Context.Value("mdns.domain").(string) | ||||||
|  | 	if ok { | ||||||
|  | 		domain = d | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return &mdnsRegistry{ | 	return &mdnsRegistry{ | ||||||
| 		opts:     options, | 		opts:     options, | ||||||
|  | 		domain:   domain, | ||||||
| 		services: make(map[string][]*mdnsEntry), | 		services: make(map[string][]*mdnsEntry), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -66,7 +87,7 @@ func (m *mdnsRegistry) Register(service *Service, opts ...RegisterOption) error | |||||||
| 		s, err := mdns.NewMDNSService( | 		s, err := mdns.NewMDNSService( | ||||||
| 			service.Name, | 			service.Name, | ||||||
| 			"_services", | 			"_services", | ||||||
| 			"", | 			m.domain+".", | ||||||
| 			"", | 			"", | ||||||
| 			9999, | 			9999, | ||||||
| 			[]net.IP{net.ParseIP("0.0.0.0")}, | 			[]net.IP{net.ParseIP("0.0.0.0")}, | ||||||
| @@ -141,7 +162,7 @@ func (m *mdnsRegistry) Register(service *Service, opts ...RegisterOption) error | |||||||
| 		s, err := mdns.NewMDNSService( | 		s, err := mdns.NewMDNSService( | ||||||
| 			node.Id, | 			node.Id, | ||||||
| 			service.Name, | 			service.Name, | ||||||
| 			"", | 			m.domain+".", | ||||||
| 			"", | 			"", | ||||||
| 			port, | 			port, | ||||||
| 			[]net.IP{net.ParseIP(host)}, | 			[]net.IP{net.ParseIP(host)}, | ||||||
| @@ -214,6 +235,8 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { | |||||||
| 	p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) | 	p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) | ||||||
| 	// set entries channel | 	// set entries channel | ||||||
| 	p.Entries = entries | 	p.Entries = entries | ||||||
|  | 	// set the domain | ||||||
|  | 	p.Domain = m.domain | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		for { | 		for { | ||||||
| @@ -223,7 +246,9 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { | |||||||
| 				if p.Service == "_services" { | 				if p.Service == "_services" { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  | 				if p.Domain != m.domain { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
| 				if e.TTL == 0 { | 				if e.TTL == 0 { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
| @@ -288,6 +313,8 @@ func (m *mdnsRegistry) ListServices() ([]*Service, error) { | |||||||
| 	p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) | 	p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) | ||||||
| 	// set entries channel | 	// set entries channel | ||||||
| 	p.Entries = entries | 	p.Entries = entries | ||||||
|  | 	// set domain | ||||||
|  | 	p.Domain = m.domain | ||||||
|  |  | ||||||
| 	var services []*Service | 	var services []*Service | ||||||
|  |  | ||||||
| @@ -298,7 +325,9 @@ func (m *mdnsRegistry) ListServices() ([]*Service, error) { | |||||||
| 				if e.TTL == 0 { | 				if e.TTL == 0 { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  | 				if !strings.HasSuffix(e.Name, p.Domain+".") { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
| 				name := strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+".") | 				name := strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+".") | ||||||
| 				if !serviceMap[name] { | 				if !serviceMap[name] { | ||||||
| 					serviceMap[name] = true | 					serviceMap[name] = true | ||||||
| @@ -329,9 +358,10 @@ func (m *mdnsRegistry) Watch(opts ...WatchOption) (Watcher, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	md := &mdnsWatcher{ | 	md := &mdnsWatcher{ | ||||||
| 		wo:   wo, | 		wo:     wo, | ||||||
| 		ch:   make(chan *mdns.ServiceEntry, 32), | 		ch:     make(chan *mdns.ServiceEntry, 32), | ||||||
| 		exit: make(chan struct{}), | 		exit:   make(chan struct{}), | ||||||
|  | 		domain: m.domain, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
|   | |||||||
| @@ -11,6 +11,8 @@ type mdnsWatcher struct { | |||||||
| 	wo   WatchOptions | 	wo   WatchOptions | ||||||
| 	ch   chan *mdns.ServiceEntry | 	ch   chan *mdns.ServiceEntry | ||||||
| 	exit chan struct{} | 	exit chan struct{} | ||||||
|  | 	// the mdns domain | ||||||
|  | 	domain string | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *mdnsWatcher) Next() (*Result, error) { | func (m *mdnsWatcher) Next() (*Result, error) { | ||||||
| @@ -46,13 +48,14 @@ func (m *mdnsWatcher) Next() (*Result, error) { | |||||||
| 				Endpoints: txt.Endpoints, | 				Endpoints: txt.Endpoints, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// TODO: don't hardcode .local. | 			// skip anything without the domain we care about | ||||||
| 			if !strings.HasSuffix(e.Name, "."+service.Name+".local.") { | 			suffix := fmt.Sprintf(".%s.%s.", service.Name, m.domain) | ||||||
|  | 			if !strings.HasSuffix(e.Name, suffix) { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			service.Nodes = append(service.Nodes, &Node{ | 			service.Nodes = append(service.Nodes, &Node{ | ||||||
| 				Id:       strings.TrimSuffix(e.Name, "."+service.Name+".local."), | 				Id:       strings.TrimSuffix(e.Name, suffix), | ||||||
| 				Address:  fmt.Sprintf("%s:%d", e.AddrV4.String(), e.Port), | 				Address:  fmt.Sprintf("%s:%d", e.AddrV4.String(), e.Port), | ||||||
| 				Metadata: txt.Metadata, | 				Metadata: txt.Metadata, | ||||||
| 			}) | 			}) | ||||||
|   | |||||||
							
								
								
									
										224
									
								
								registry/proto/registry.micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								registry/proto/registry.micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | |||||||
|  | // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||||
|  | // source: micro/go-micro/registry/proto/registry.proto | ||||||
|  |  | ||||||
|  | package go_micro_registry | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	fmt "fmt" | ||||||
|  | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	context "context" | ||||||
|  | 	client "github.com/micro/go-micro/client" | ||||||
|  | 	server "github.com/micro/go-micro/server" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ = proto.Marshal | ||||||
|  | var _ = fmt.Errorf | ||||||
|  | var _ = math.Inf | ||||||
|  |  | ||||||
|  | // This is a compile-time assertion to ensure that this generated file | ||||||
|  | // is compatible with the proto package it is being compiled against. | ||||||
|  | // A compilation error at this line likely means your copy of the | ||||||
|  | // proto package needs to be updated. | ||||||
|  | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ context.Context | ||||||
|  | var _ client.Option | ||||||
|  | var _ server.Option | ||||||
|  |  | ||||||
|  | // Client API for Registry service | ||||||
|  |  | ||||||
|  | type RegistryService interface { | ||||||
|  | 	GetService(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) | ||||||
|  | 	Register(ctx context.Context, in *Service, opts ...client.CallOption) (*EmptyResponse, error) | ||||||
|  | 	Deregister(ctx context.Context, in *Service, opts ...client.CallOption) (*EmptyResponse, error) | ||||||
|  | 	ListServices(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) | ||||||
|  | 	Watch(ctx context.Context, in *WatchRequest, opts ...client.CallOption) (Registry_WatchService, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryService struct { | ||||||
|  | 	c    client.Client | ||||||
|  | 	name string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewRegistryService(name string, c client.Client) RegistryService { | ||||||
|  | 	if c == nil { | ||||||
|  | 		c = client.NewClient() | ||||||
|  | 	} | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		name = "go.micro.registry" | ||||||
|  | 	} | ||||||
|  | 	return ®istryService{ | ||||||
|  | 		c:    c, | ||||||
|  | 		name: name, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryService) GetService(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Registry.GetService", in) | ||||||
|  | 	out := new(GetResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryService) Register(ctx context.Context, in *Service, opts ...client.CallOption) (*EmptyResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Registry.Register", in) | ||||||
|  | 	out := new(EmptyResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryService) Deregister(ctx context.Context, in *Service, opts ...client.CallOption) (*EmptyResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Registry.Deregister", in) | ||||||
|  | 	out := new(EmptyResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryService) ListServices(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Registry.ListServices", in) | ||||||
|  | 	out := new(ListResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryService) Watch(ctx context.Context, in *WatchRequest, opts ...client.CallOption) (Registry_WatchService, error) { | ||||||
|  | 	req := c.c.NewRequest(c.name, "Registry.Watch", &WatchRequest{}) | ||||||
|  | 	stream, err := c.c.Stream(ctx, req, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if err := stream.Send(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return ®istryServiceWatch{stream}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Registry_WatchService interface { | ||||||
|  | 	SendMsg(interface{}) error | ||||||
|  | 	RecvMsg(interface{}) error | ||||||
|  | 	Close() error | ||||||
|  | 	Recv() (*Result, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryServiceWatch struct { | ||||||
|  | 	stream client.Stream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryServiceWatch) Close() error { | ||||||
|  | 	return x.stream.Close() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryServiceWatch) SendMsg(m interface{}) error { | ||||||
|  | 	return x.stream.Send(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryServiceWatch) RecvMsg(m interface{}) error { | ||||||
|  | 	return x.stream.Recv(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryServiceWatch) Recv() (*Result, error) { | ||||||
|  | 	m := new(Result) | ||||||
|  | 	err := x.stream.Recv(m) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return m, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Server API for Registry service | ||||||
|  |  | ||||||
|  | type RegistryHandler interface { | ||||||
|  | 	GetService(context.Context, *GetRequest, *GetResponse) error | ||||||
|  | 	Register(context.Context, *Service, *EmptyResponse) error | ||||||
|  | 	Deregister(context.Context, *Service, *EmptyResponse) error | ||||||
|  | 	ListServices(context.Context, *ListRequest, *ListResponse) error | ||||||
|  | 	Watch(context.Context, *WatchRequest, Registry_WatchStream) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RegisterRegistryHandler(s server.Server, hdlr RegistryHandler, opts ...server.HandlerOption) error { | ||||||
|  | 	type registry interface { | ||||||
|  | 		GetService(ctx context.Context, in *GetRequest, out *GetResponse) error | ||||||
|  | 		Register(ctx context.Context, in *Service, out *EmptyResponse) error | ||||||
|  | 		Deregister(ctx context.Context, in *Service, out *EmptyResponse) error | ||||||
|  | 		ListServices(ctx context.Context, in *ListRequest, out *ListResponse) error | ||||||
|  | 		Watch(ctx context.Context, stream server.Stream) error | ||||||
|  | 	} | ||||||
|  | 	type Registry struct { | ||||||
|  | 		registry | ||||||
|  | 	} | ||||||
|  | 	h := ®istryHandler{hdlr} | ||||||
|  | 	return s.Handle(s.NewHandler(&Registry{h}, opts...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryHandler struct { | ||||||
|  | 	RegistryHandler | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *registryHandler) GetService(ctx context.Context, in *GetRequest, out *GetResponse) error { | ||||||
|  | 	return h.RegistryHandler.GetService(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *registryHandler) Register(ctx context.Context, in *Service, out *EmptyResponse) error { | ||||||
|  | 	return h.RegistryHandler.Register(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *registryHandler) Deregister(ctx context.Context, in *Service, out *EmptyResponse) error { | ||||||
|  | 	return h.RegistryHandler.Deregister(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *registryHandler) ListServices(ctx context.Context, in *ListRequest, out *ListResponse) error { | ||||||
|  | 	return h.RegistryHandler.ListServices(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *registryHandler) Watch(ctx context.Context, stream server.Stream) error { | ||||||
|  | 	m := new(WatchRequest) | ||||||
|  | 	if err := stream.Recv(m); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return h.RegistryHandler.Watch(ctx, m, ®istryWatchStream{stream}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Registry_WatchStream interface { | ||||||
|  | 	SendMsg(interface{}) error | ||||||
|  | 	RecvMsg(interface{}) error | ||||||
|  | 	Close() error | ||||||
|  | 	Send(*Result) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryWatchStream struct { | ||||||
|  | 	stream server.Stream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchStream) Close() error { | ||||||
|  | 	return x.stream.Close() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchStream) SendMsg(m interface{}) error { | ||||||
|  | 	return x.stream.Send(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchStream) RecvMsg(m interface{}) error { | ||||||
|  | 	return x.stream.Recv(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchStream) Send(m *Result) error { | ||||||
|  | 	return x.stream.Send(m) | ||||||
|  | } | ||||||
							
								
								
									
										848
									
								
								registry/proto/registry.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										848
									
								
								registry/proto/registry.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,848 @@ | |||||||
|  | // Code generated by protoc-gen-go. DO NOT EDIT. | ||||||
|  | // source: micro/go-micro/registry/proto/registry.proto | ||||||
|  |  | ||||||
|  | package go_micro_registry | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	context "context" | ||||||
|  | 	fmt "fmt" | ||||||
|  | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	grpc "google.golang.org/grpc" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ = proto.Marshal | ||||||
|  | var _ = fmt.Errorf | ||||||
|  | var _ = math.Inf | ||||||
|  |  | ||||||
|  | // This is a compile-time assertion to ensure that this generated file | ||||||
|  | // is compatible with the proto package it is being compiled against. | ||||||
|  | // A compilation error at this line likely means your copy of the | ||||||
|  | // proto package needs to be updated. | ||||||
|  | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||||
|  |  | ||||||
|  | // Service represents a go-micro service | ||||||
|  | type Service struct { | ||||||
|  | 	Name                 string            `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||||
|  | 	Version              string            `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` | ||||||
|  | 	Metadata             map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` | ||||||
|  | 	Endpoints            []*Endpoint       `protobuf:"bytes,4,rep,name=endpoints,proto3" json:"endpoints,omitempty"` | ||||||
|  | 	Nodes                []*Node           `protobuf:"bytes,5,rep,name=nodes,proto3" json:"nodes,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{}          `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte            `json:"-"` | ||||||
|  | 	XXX_sizecache        int32             `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) Reset()         { *m = Service{} } | ||||||
|  | func (m *Service) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Service) ProtoMessage()    {} | ||||||
|  | func (*Service) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{0} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Service.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Service) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Service.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Service) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Service.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Service) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Service.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Service) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Service.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Service proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Service) GetName() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Name | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) GetVersion() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Version | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) GetMetadata() map[string]string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Metadata | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) GetEndpoints() []*Endpoint { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Endpoints | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Service) GetNodes() []*Node { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Nodes | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Node represents the node the service is on | ||||||
|  | type Node struct { | ||||||
|  | 	Id                   string            `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` | ||||||
|  | 	Address              string            `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` | ||||||
|  | 	Port                 int64             `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"` | ||||||
|  | 	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:"-"` | ||||||
|  | 	XXX_unrecognized     []byte            `json:"-"` | ||||||
|  | 	XXX_sizecache        int32             `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) Reset()         { *m = Node{} } | ||||||
|  | func (m *Node) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Node) ProtoMessage()    {} | ||||||
|  | func (*Node) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{1} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Node.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Node.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Node.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Node.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Node) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Node.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Node proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Node) GetId() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Id | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) GetAddress() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Address | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) GetPort() int64 { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Port | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Node) GetMetadata() map[string]string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Metadata | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Endpoint is a endpoint provided by a service | ||||||
|  | type Endpoint struct { | ||||||
|  | 	Name                 string            `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||||
|  | 	Request              *Value            `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` | ||||||
|  | 	Response             *Value            `protobuf:"bytes,3,opt,name=response,proto3" json:"response,omitempty"` | ||||||
|  | 	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:"-"` | ||||||
|  | 	XXX_unrecognized     []byte            `json:"-"` | ||||||
|  | 	XXX_sizecache        int32             `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Endpoint) Reset()         { *m = Endpoint{} } | ||||||
|  | func (m *Endpoint) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Endpoint) ProtoMessage()    {} | ||||||
|  | func (*Endpoint) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{2} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Endpoint) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Endpoint.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Endpoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Endpoint.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Endpoint) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Endpoint.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Endpoint) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Endpoint.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Endpoint) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Endpoint.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Endpoint proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Endpoint) GetName() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Name | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Endpoint) GetRequest() *Value { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Request | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Endpoint) GetResponse() *Value { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Response | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Endpoint) GetMetadata() map[string]string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Metadata | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Value is an opaque value for a request or response | ||||||
|  | type Value struct { | ||||||
|  | 	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||||
|  | 	Type                 string   `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` | ||||||
|  | 	Values               []*Value `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Value) Reset()         { *m = Value{} } | ||||||
|  | func (m *Value) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Value) ProtoMessage()    {} | ||||||
|  | func (*Value) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{3} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Value) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Value.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Value.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Value) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Value.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Value) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Value.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Value) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Value.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Value proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Value) GetName() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Name | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Value) GetType() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Type | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Value) GetValues() []*Value { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Values | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Result is returns by the watcher | ||||||
|  | type Result struct { | ||||||
|  | 	Action               string   `protobuf:"bytes,1,opt,name=action,proto3" json:"action,omitempty"` | ||||||
|  | 	Service              *Service `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` | ||||||
|  | 	Timestamp            int64    `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Result) Reset()         { *m = Result{} } | ||||||
|  | func (m *Result) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*Result) ProtoMessage()    {} | ||||||
|  | func (*Result) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{4} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Result) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Result.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Result) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Result.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Result) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Result.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Result) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Result.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Result) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Result.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_Result proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *Result) GetAction() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Action | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Result) GetService() *Service { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Service | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Result) GetTimestamp() int64 { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Timestamp | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type EmptyResponse struct { | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *EmptyResponse) Reset()         { *m = EmptyResponse{} } | ||||||
|  | func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*EmptyResponse) ProtoMessage()    {} | ||||||
|  | func (*EmptyResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{5} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_EmptyResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *EmptyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_EmptyResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *EmptyResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_EmptyResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *EmptyResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_EmptyResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *EmptyResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_EmptyResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_EmptyResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | type GetRequest struct { | ||||||
|  | 	Service              string   `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *GetRequest) Reset()         { *m = GetRequest{} } | ||||||
|  | func (m *GetRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*GetRequest) ProtoMessage()    {} | ||||||
|  | func (*GetRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{6} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *GetRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_GetRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *GetRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_GetRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *GetRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_GetRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *GetRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_GetRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_GetRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *GetRequest) GetService() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Service | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type GetResponse struct { | ||||||
|  | 	Services             []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{}   `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte     `json:"-"` | ||||||
|  | 	XXX_sizecache        int32      `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *GetResponse) Reset()         { *m = GetResponse{} } | ||||||
|  | func (m *GetResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*GetResponse) ProtoMessage()    {} | ||||||
|  | func (*GetResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{7} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *GetResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_GetResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *GetResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_GetResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *GetResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_GetResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *GetResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_GetResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_GetResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *GetResponse) GetServices() []*Service { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Services | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type ListRequest struct { | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListRequest) Reset()         { *m = ListRequest{} } | ||||||
|  | func (m *ListRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*ListRequest) ProtoMessage()    {} | ||||||
|  | func (*ListRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{8} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ListRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ListRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ListRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ListRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_ListRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | type ListResponse struct { | ||||||
|  | 	Services             []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{}   `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte     `json:"-"` | ||||||
|  | 	XXX_sizecache        int32      `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListResponse) Reset()         { *m = ListResponse{} } | ||||||
|  | func (m *ListResponse) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*ListResponse) ProtoMessage()    {} | ||||||
|  | func (*ListResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{9} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *ListResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ListResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ListResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ListResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ListResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_ListResponse proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *ListResponse) GetServices() []*Service { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Services | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type WatchRequest struct { | ||||||
|  | 	// service is optional | ||||||
|  | 	Service              string   `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *WatchRequest) Reset()         { *m = WatchRequest{} } | ||||||
|  | func (m *WatchRequest) String() string { return proto.CompactTextString(m) } | ||||||
|  | func (*WatchRequest) ProtoMessage()    {} | ||||||
|  | func (*WatchRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_f287a6b809166ad2, []int{10} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *WatchRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_WatchRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *WatchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_WatchRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *WatchRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_WatchRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *WatchRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_WatchRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *WatchRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_WatchRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var xxx_messageInfo_WatchRequest proto.InternalMessageInfo | ||||||
|  |  | ||||||
|  | func (m *WatchRequest) GetService() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Service | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	proto.RegisterType((*Service)(nil), "go.micro.registry.Service") | ||||||
|  | 	proto.RegisterMapType((map[string]string)(nil), "go.micro.registry.Service.MetadataEntry") | ||||||
|  | 	proto.RegisterType((*Node)(nil), "go.micro.registry.Node") | ||||||
|  | 	proto.RegisterMapType((map[string]string)(nil), "go.micro.registry.Node.MetadataEntry") | ||||||
|  | 	proto.RegisterType((*Endpoint)(nil), "go.micro.registry.Endpoint") | ||||||
|  | 	proto.RegisterMapType((map[string]string)(nil), "go.micro.registry.Endpoint.MetadataEntry") | ||||||
|  | 	proto.RegisterType((*Value)(nil), "go.micro.registry.Value") | ||||||
|  | 	proto.RegisterType((*Result)(nil), "go.micro.registry.Result") | ||||||
|  | 	proto.RegisterType((*EmptyResponse)(nil), "go.micro.registry.EmptyResponse") | ||||||
|  | 	proto.RegisterType((*GetRequest)(nil), "go.micro.registry.GetRequest") | ||||||
|  | 	proto.RegisterType((*GetResponse)(nil), "go.micro.registry.GetResponse") | ||||||
|  | 	proto.RegisterType((*ListRequest)(nil), "go.micro.registry.ListRequest") | ||||||
|  | 	proto.RegisterType((*ListResponse)(nil), "go.micro.registry.ListResponse") | ||||||
|  | 	proto.RegisterType((*WatchRequest)(nil), "go.micro.registry.WatchRequest") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	proto.RegisterFile("micro/go-micro/registry/proto/registry.proto", fileDescriptor_f287a6b809166ad2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var fileDescriptor_f287a6b809166ad2 = []byte{ | ||||||
|  | 	// 577 bytes of a gzipped FileDescriptorProto | ||||||
|  | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x6d, 0x8b, 0xd3, 0x4c, | ||||||
|  | 	0x14, 0x6d, 0x92, 0xbe, 0xde, 0x6e, 0x9f, 0x47, 0x2f, 0xa2, 0x31, 0xbe, 0x95, 0x80, 0x52, 0xc1, | ||||||
|  | 	0xcd, 0x2e, 0x75, 0x11, 0x5f, 0x3e, 0x09, 0x5b, 0x17, 0x64, 0x57, 0x70, 0x04, 0xfd, 0x1c, 0x9b, | ||||||
|  | 	0x4b, 0x0d, 0x6e, 0x5e, 0x9c, 0x99, 0x16, 0xfa, 0x1f, 0x04, 0xff, 0x84, 0x3f, 0xc5, 0x1f, 0x26, | ||||||
|  | 	0x99, 0xcc, 0x34, 0x5d, 0x36, 0xa9, 0x1f, 0x56, 0xbf, 0xcd, 0xcd, 0x9c, 0x73, 0xe6, 0x9e, 0x73, | ||||||
|  | 	0x67, 0x5a, 0x78, 0x92, 0xc4, 0x73, 0x9e, 0x1d, 0x2c, 0xb2, 0xfd, 0x72, 0xc1, 0x69, 0x11, 0x0b, | ||||||
|  | 	0xc9, 0xd7, 0x07, 0x39, 0xcf, 0x64, 0x55, 0x06, 0xaa, 0xc4, 0xeb, 0x8b, 0x2c, 0x50, 0xb8, 0xc0, | ||||||
|  | 	0x6c, 0xf8, 0x3f, 0x6d, 0xe8, 0x7d, 0x20, 0xbe, 0x8a, 0xe7, 0x84, 0x08, 0xed, 0x34, 0x4c, 0xc8, | ||||||
|  | 	0xb5, 0xc6, 0xd6, 0x64, 0xc0, 0xd4, 0x1a, 0x5d, 0xe8, 0xad, 0x88, 0x8b, 0x38, 0x4b, 0x5d, 0x5b, | ||||||
|  | 	0x7d, 0x36, 0x25, 0x1e, 0x43, 0x3f, 0x21, 0x19, 0x46, 0xa1, 0x0c, 0x5d, 0x67, 0xec, 0x4c, 0x86, | ||||||
|  | 	0xd3, 0x49, 0x70, 0x49, 0x3f, 0xd0, 0xda, 0xc1, 0x99, 0x86, 0xce, 0x52, 0xc9, 0xd7, 0x6c, 0xc3, | ||||||
|  | 	0xc4, 0x17, 0x30, 0xa0, 0x34, 0xca, 0xb3, 0x38, 0x95, 0xc2, 0x6d, 0x2b, 0x99, 0x3b, 0x35, 0x32, | ||||||
|  | 	0x33, 0x8d, 0x61, 0x15, 0x1a, 0xf7, 0xa1, 0x93, 0x66, 0x11, 0x09, 0xb7, 0xa3, 0x68, 0xb7, 0x6a, | ||||||
|  | 	0x68, 0xef, 0xb2, 0x88, 0x58, 0x89, 0xf2, 0x5e, 0xc1, 0xe8, 0x42, 0x13, 0x78, 0x0d, 0x9c, 0xaf, | ||||||
|  | 	0xb4, 0xd6, 0x6e, 0x8b, 0x25, 0xde, 0x80, 0xce, 0x2a, 0x3c, 0x5f, 0x92, 0xb6, 0x5a, 0x16, 0x2f, | ||||||
|  | 	0xed, 0xe7, 0x96, 0xff, 0xcb, 0x82, 0x76, 0x21, 0x86, 0xff, 0x81, 0x1d, 0x47, 0x9a, 0x63, 0xc7, | ||||||
|  | 	0x51, 0x91, 0x4f, 0x18, 0x45, 0x9c, 0x84, 0x30, 0xf9, 0xe8, 0xb2, 0x48, 0x33, 0xcf, 0xb8, 0x74, | ||||||
|  | 	0x9d, 0xb1, 0x35, 0x71, 0x98, 0x5a, 0xe3, 0xeb, 0xad, 0xcc, 0x4a, 0xb3, 0x0f, 0x1b, 0xba, 0x6e, | ||||||
|  | 	0x0a, 0xec, 0x6a, 0x36, 0xbe, 0xdb, 0xd0, 0x37, 0x51, 0xd6, 0x8e, 0x7b, 0x0a, 0x3d, 0x4e, 0xdf, | ||||||
|  | 	0x96, 0x24, 0xa4, 0x22, 0x0f, 0xa7, 0x6e, 0x4d, 0x7f, 0x1f, 0x0b, 0x3d, 0x66, 0x80, 0x78, 0x04, | ||||||
|  | 	0x7d, 0x4e, 0x22, 0xcf, 0x52, 0x41, 0xca, 0xec, 0x2e, 0xd2, 0x06, 0x89, 0xb3, 0x4b, 0x51, 0x3c, | ||||||
|  | 	0xde, 0x31, 0xf7, 0x7f, 0x13, 0x47, 0x08, 0x1d, 0xd5, 0x56, 0x6d, 0x14, 0x08, 0x6d, 0xb9, 0xce, | ||||||
|  | 	0x0d, 0x4b, 0xad, 0xf1, 0x10, 0xba, 0x8a, 0x2d, 0xf4, 0x8d, 0x6f, 0x36, 0xaa, 0x71, 0xbe, 0x84, | ||||||
|  | 	0x2e, 0x23, 0xb1, 0x3c, 0x97, 0x78, 0x13, 0xba, 0xe1, 0x5c, 0x16, 0x0f, 0xa9, 0x3c, 0x45, 0x57, | ||||||
|  | 	0x78, 0x04, 0x3d, 0x51, 0x3e, 0x12, 0x1d, 0xb9, 0xd7, 0xfc, 0x8c, 0x98, 0x81, 0xe2, 0x5d, 0x18, | ||||||
|  | 	0xc8, 0x38, 0x21, 0x21, 0xc3, 0x24, 0xd7, 0x57, 0xac, 0xfa, 0xe0, 0xff, 0x0f, 0xa3, 0x59, 0x92, | ||||||
|  | 	0xcb, 0x35, 0xd3, 0x69, 0xfb, 0x8f, 0x00, 0x4e, 0x48, 0x32, 0x3d, 0x31, 0xb7, 0x3a, 0xb2, 0xec, | ||||||
|  | 	0xc5, 0x94, 0xfe, 0x0c, 0x86, 0x0a, 0xa7, 0x87, 0xf4, 0x0c, 0xfa, 0x7a, 0x47, 0xb8, 0x96, 0x72, | ||||||
|  | 	0xbc, 0xab, 0xb9, 0x0d, 0xd6, 0x1f, 0xc1, 0xf0, 0x34, 0x16, 0xe6, 0x3c, 0xff, 0x0d, 0xec, 0x95, | ||||||
|  | 	0xe5, 0x15, 0x65, 0x27, 0xb0, 0xf7, 0x29, 0x94, 0xf3, 0x2f, 0x7f, 0xf4, 0x31, 0xfd, 0xe1, 0x40, | ||||||
|  | 	0x9f, 0x69, 0x21, 0x3c, 0x53, 0xe6, 0xcd, 0xaf, 0xdc, 0xbd, 0x9a, 0xa3, 0xaa, 0x6c, 0xbc, 0xfb, | ||||||
|  | 	0x4d, 0xdb, 0x3a, 0xc9, 0x16, 0xbe, 0x35, 0xd2, 0xc4, 0x71, 0x47, 0xdf, 0xde, 0xb8, 0xee, 0x3e, | ||||||
|  | 	0x5f, 0x98, 0x4a, 0x0b, 0x4f, 0x01, 0x8e, 0x89, 0xff, 0x2d, 0xb5, 0xf7, 0x65, 0xce, 0x9a, 0x22, | ||||||
|  | 	0xb0, 0xce, 0xcb, 0xd6, 0x5c, 0xbc, 0x07, 0x8d, 0xfb, 0x1b, 0xc9, 0x13, 0xe8, 0xa8, 0xc8, 0xb1, | ||||||
|  | 	0x0e, 0xbb, 0x3d, 0x0c, 0xef, 0x76, 0x0d, 0xa0, 0xbc, 0xfa, 0x7e, 0xeb, 0xd0, 0xfa, 0xdc, 0x55, | ||||||
|  | 	0x7f, 0x41, 0x4f, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x0b, 0x12, 0xd6, 0xb2, 0x06, 0x00, | ||||||
|  | 	0x00, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ context.Context | ||||||
|  | var _ grpc.ClientConn | ||||||
|  |  | ||||||
|  | // This is a compile-time assertion to ensure that this generated file | ||||||
|  | // is compatible with the grpc package it is being compiled against. | ||||||
|  | const _ = grpc.SupportPackageIsVersion4 | ||||||
|  |  | ||||||
|  | // RegistryClient is the client API for Registry service. | ||||||
|  | // | ||||||
|  | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. | ||||||
|  | type RegistryClient interface { | ||||||
|  | 	GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) | ||||||
|  | 	Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) | ||||||
|  | 	Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) | ||||||
|  | 	ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) | ||||||
|  | 	Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryClient struct { | ||||||
|  | 	cc *grpc.ClientConn | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewRegistryClient(cc *grpc.ClientConn) RegistryClient { | ||||||
|  | 	return ®istryClient{cc} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryClient) GetService(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { | ||||||
|  | 	out := new(GetResponse) | ||||||
|  | 	err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/GetService", in, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryClient) Register(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { | ||||||
|  | 	out := new(EmptyResponse) | ||||||
|  | 	err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Register", in, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryClient) Deregister(ctx context.Context, in *Service, opts ...grpc.CallOption) (*EmptyResponse, error) { | ||||||
|  | 	out := new(EmptyResponse) | ||||||
|  | 	err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/Deregister", in, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryClient) ListServices(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { | ||||||
|  | 	out := new(ListResponse) | ||||||
|  | 	err := c.cc.Invoke(ctx, "/go.micro.registry.Registry/ListServices", in, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *registryClient) Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Registry_WatchClient, error) { | ||||||
|  | 	stream, err := c.cc.NewStream(ctx, &_Registry_serviceDesc.Streams[0], "/go.micro.registry.Registry/Watch", opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	x := ®istryWatchClient{stream} | ||||||
|  | 	if err := x.ClientStream.SendMsg(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if err := x.ClientStream.CloseSend(); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return x, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Registry_WatchClient interface { | ||||||
|  | 	Recv() (*Result, error) | ||||||
|  | 	grpc.ClientStream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryWatchClient struct { | ||||||
|  | 	grpc.ClientStream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchClient) Recv() (*Result, error) { | ||||||
|  | 	m := new(Result) | ||||||
|  | 	if err := x.ClientStream.RecvMsg(m); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return m, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RegistryServer is the server API for Registry service. | ||||||
|  | type RegistryServer interface { | ||||||
|  | 	GetService(context.Context, *GetRequest) (*GetResponse, error) | ||||||
|  | 	Register(context.Context, *Service) (*EmptyResponse, error) | ||||||
|  | 	Deregister(context.Context, *Service) (*EmptyResponse, error) | ||||||
|  | 	ListServices(context.Context, *ListRequest) (*ListResponse, error) | ||||||
|  | 	Watch(*WatchRequest, Registry_WatchServer) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RegisterRegistryServer(s *grpc.Server, srv RegistryServer) { | ||||||
|  | 	s.RegisterService(&_Registry_serviceDesc, srv) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func _Registry_GetService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||||
|  | 	in := new(GetRequest) | ||||||
|  | 	if err := dec(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if interceptor == nil { | ||||||
|  | 		return srv.(RegistryServer).GetService(ctx, in) | ||||||
|  | 	} | ||||||
|  | 	info := &grpc.UnaryServerInfo{ | ||||||
|  | 		Server:     srv, | ||||||
|  | 		FullMethod: "/go.micro.registry.Registry/GetService", | ||||||
|  | 	} | ||||||
|  | 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||||
|  | 		return srv.(RegistryServer).GetService(ctx, req.(*GetRequest)) | ||||||
|  | 	} | ||||||
|  | 	return interceptor(ctx, in, info, handler) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func _Registry_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||||
|  | 	in := new(Service) | ||||||
|  | 	if err := dec(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if interceptor == nil { | ||||||
|  | 		return srv.(RegistryServer).Register(ctx, in) | ||||||
|  | 	} | ||||||
|  | 	info := &grpc.UnaryServerInfo{ | ||||||
|  | 		Server:     srv, | ||||||
|  | 		FullMethod: "/go.micro.registry.Registry/Register", | ||||||
|  | 	} | ||||||
|  | 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||||
|  | 		return srv.(RegistryServer).Register(ctx, req.(*Service)) | ||||||
|  | 	} | ||||||
|  | 	return interceptor(ctx, in, info, handler) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func _Registry_Deregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||||
|  | 	in := new(Service) | ||||||
|  | 	if err := dec(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if interceptor == nil { | ||||||
|  | 		return srv.(RegistryServer).Deregister(ctx, in) | ||||||
|  | 	} | ||||||
|  | 	info := &grpc.UnaryServerInfo{ | ||||||
|  | 		Server:     srv, | ||||||
|  | 		FullMethod: "/go.micro.registry.Registry/Deregister", | ||||||
|  | 	} | ||||||
|  | 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||||
|  | 		return srv.(RegistryServer).Deregister(ctx, req.(*Service)) | ||||||
|  | 	} | ||||||
|  | 	return interceptor(ctx, in, info, handler) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func _Registry_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||||
|  | 	in := new(ListRequest) | ||||||
|  | 	if err := dec(in); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if interceptor == nil { | ||||||
|  | 		return srv.(RegistryServer).ListServices(ctx, in) | ||||||
|  | 	} | ||||||
|  | 	info := &grpc.UnaryServerInfo{ | ||||||
|  | 		Server:     srv, | ||||||
|  | 		FullMethod: "/go.micro.registry.Registry/ListServices", | ||||||
|  | 	} | ||||||
|  | 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||||
|  | 		return srv.(RegistryServer).ListServices(ctx, req.(*ListRequest)) | ||||||
|  | 	} | ||||||
|  | 	return interceptor(ctx, in, info, handler) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func _Registry_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { | ||||||
|  | 	m := new(WatchRequest) | ||||||
|  | 	if err := stream.RecvMsg(m); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return srv.(RegistryServer).Watch(m, ®istryWatchServer{stream}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Registry_WatchServer interface { | ||||||
|  | 	Send(*Result) error | ||||||
|  | 	grpc.ServerStream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type registryWatchServer struct { | ||||||
|  | 	grpc.ServerStream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *registryWatchServer) Send(m *Result) error { | ||||||
|  | 	return x.ServerStream.SendMsg(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var _Registry_serviceDesc = grpc.ServiceDesc{ | ||||||
|  | 	ServiceName: "go.micro.registry.Registry", | ||||||
|  | 	HandlerType: (*RegistryServer)(nil), | ||||||
|  | 	Methods: []grpc.MethodDesc{ | ||||||
|  | 		{ | ||||||
|  | 			MethodName: "GetService", | ||||||
|  | 			Handler:    _Registry_GetService_Handler, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			MethodName: "Register", | ||||||
|  | 			Handler:    _Registry_Register_Handler, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			MethodName: "Deregister", | ||||||
|  | 			Handler:    _Registry_Deregister_Handler, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			MethodName: "ListServices", | ||||||
|  | 			Handler:    _Registry_ListServices_Handler, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	Streams: []grpc.StreamDesc{ | ||||||
|  | 		{ | ||||||
|  | 			StreamName:    "Watch", | ||||||
|  | 			Handler:       _Registry_Watch_Handler, | ||||||
|  | 			ServerStreams: true, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	Metadata: "micro/go-micro/registry/proto/registry.proto", | ||||||
|  | } | ||||||
							
								
								
									
										73
									
								
								registry/proto/registry.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								registry/proto/registry.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | syntax = "proto3"; | ||||||
|  |  | ||||||
|  | package go.micro.registry; | ||||||
|  |  | ||||||
|  | service Registry { | ||||||
|  | 	rpc GetService(GetRequest) returns (GetResponse) {}; | ||||||
|  | 	rpc Register(Service) returns (EmptyResponse) {}; | ||||||
|  | 	rpc Deregister(Service) returns (EmptyResponse) {}; | ||||||
|  | 	rpc ListServices(ListRequest) returns (ListResponse) {}; | ||||||
|  | 	rpc Watch(WatchRequest) returns (stream Result) {}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Service represents a go-micro service | ||||||
|  | message Service { | ||||||
|  | 	string name = 1; | ||||||
|  | 	string version = 2; | ||||||
|  | 	map<string,string> metadata = 3; | ||||||
|  | 	repeated Endpoint endpoints = 4; | ||||||
|  | 	repeated Node nodes = 5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Node represents the node the service is on | ||||||
|  | message Node { | ||||||
|  | 	string id = 1; | ||||||
|  | 	string address = 2; | ||||||
|  | 	int64 port = 3; | ||||||
|  | 	map<string,string> metadata = 4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Endpoint is a endpoint provided by a service | ||||||
|  | message Endpoint { | ||||||
|  | 	string name = 1; | ||||||
|  | 	Value request = 2; | ||||||
|  | 	Value response = 3; | ||||||
|  | 	map<string, string> metadata = 4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Value is an opaque value for a request or response | ||||||
|  | message Value { | ||||||
|  | 	string name = 1; | ||||||
|  | 	string type = 2; | ||||||
|  | 	repeated Value values = 3; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Result is returns by the watcher | ||||||
|  | message Result { | ||||||
|  | 	string action = 1; // create, update, delete | ||||||
|  | 	Service service = 2; | ||||||
|  | 	int64 timestamp = 3; // unix timestamp | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message EmptyResponse {} | ||||||
|  |  | ||||||
|  | message GetRequest { | ||||||
|  | 	string service = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message GetResponse { | ||||||
|  | 	repeated Service services = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message ListRequest { | ||||||
|  | 	// TODO: filtering | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message ListResponse { | ||||||
|  | 	repeated Service services = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message WatchRequest { | ||||||
|  | 	// service is optional | ||||||
|  | 	string service = 1; | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								registry/service/service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								registry/service/service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | // Package service uses the registry service | ||||||
|  | package service | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	pb "github.com/micro/go-micro/registry/proto" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// The default service name | ||||||
|  | 	DefaultService = "go.micro.service" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type serviceRegistry struct { | ||||||
|  | 	opts registry.Options | ||||||
|  | 	// name of the registry | ||||||
|  | 	name string | ||||||
|  | 	// address | ||||||
|  | 	address []string | ||||||
|  | 	// client to call registry | ||||||
|  | 	client pb.RegistryService | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) callOpts() []client.CallOption { | ||||||
|  | 	var opts []client.CallOption | ||||||
|  |  | ||||||
|  | 	// set registry address | ||||||
|  | 	if len(s.address) > 0 { | ||||||
|  | 		opts = append(opts, client.WithAddress(s.address...)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// set timeout | ||||||
|  | 	if s.opts.Timeout > time.Duration(0) { | ||||||
|  | 		opts = append(opts, client.WithRequestTimeout(s.opts.Timeout)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return opts | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) Init(opts ...registry.Option) error { | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&s.opts) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) Options() registry.Options { | ||||||
|  | 	return s.opts | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) Register(srv *registry.Service, opts ...registry.RegisterOption) error { | ||||||
|  | 	var options registry.RegisterOptions | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// register the service | ||||||
|  | 	_, err := s.client.Register(context.TODO(), ToProto(srv), s.callOpts()...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) Deregister(srv *registry.Service) error { | ||||||
|  | 	// deregister the service | ||||||
|  | 	_, err := s.client.Deregister(context.TODO(), ToProto(srv), s.callOpts()...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) GetService(name string) ([]*registry.Service, error) { | ||||||
|  | 	rsp, err := s.client.GetService(context.TODO(), &pb.GetRequest{ | ||||||
|  | 		Service: name, | ||||||
|  | 	}, s.callOpts()...) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var services []*registry.Service | ||||||
|  | 	for _, service := range rsp.Services { | ||||||
|  | 		services = append(services, ToService(service)) | ||||||
|  | 	} | ||||||
|  | 	return services, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) ListServices() ([]*registry.Service, error) { | ||||||
|  | 	rsp, err := s.client.ListServices(context.TODO(), &pb.ListRequest{}, s.callOpts()...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var services []*registry.Service | ||||||
|  | 	for _, service := range rsp.Services { | ||||||
|  | 		services = append(services, ToService(service)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return services, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { | ||||||
|  | 	var options registry.WatchOptions | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	stream, err := s.client.Watch(context.TODO(), &pb.WatchRequest{ | ||||||
|  | 		Service: options.Service, | ||||||
|  | 	}, s.callOpts()...) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return newWatcher(stream), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceRegistry) String() string { | ||||||
|  | 	return s.name | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewRegistry returns a new registry service client | ||||||
|  | func NewRegistry(opts ...registry.Option) registry.Registry { | ||||||
|  | 	var options registry.Options | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// use mdns to find the service registry | ||||||
|  | 	mReg := registry.NewRegistry() | ||||||
|  |  | ||||||
|  | 	// create new client with mdns | ||||||
|  | 	cli := client.NewClient( | ||||||
|  | 		client.Registry(mReg), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// service name | ||||||
|  | 	// TODO: accept option | ||||||
|  | 	name := DefaultService | ||||||
|  |  | ||||||
|  | 	return &serviceRegistry{ | ||||||
|  | 		opts:    options, | ||||||
|  | 		name:    name, | ||||||
|  | 		address: options.Addrs, | ||||||
|  | 		client:  pb.NewRegistryService(name, cli), | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										133
									
								
								registry/service/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								registry/service/util.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | |||||||
|  | package service | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	pb "github.com/micro/go-micro/registry/proto" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func values(v []*registry.Value) []*pb.Value { | ||||||
|  | 	if len(v) == 0 { | ||||||
|  | 		return []*pb.Value{} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var vs []*pb.Value | ||||||
|  | 	for _, vi := range v { | ||||||
|  | 		vs = append(vs, &pb.Value{ | ||||||
|  | 			Name:   vi.Name, | ||||||
|  | 			Type:   vi.Type, | ||||||
|  | 			Values: values(vi.Values), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	return vs | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func toValues(v []*pb.Value) []*registry.Value { | ||||||
|  | 	if len(v) == 0 { | ||||||
|  | 		return []*registry.Value{} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var vs []*registry.Value | ||||||
|  | 	for _, vi := range v { | ||||||
|  | 		vs = append(vs, ®istry.Value{ | ||||||
|  | 			Name:   vi.Name, | ||||||
|  | 			Type:   vi.Type, | ||||||
|  | 			Values: toValues(vi.Values), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	return vs | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ToProto(s *registry.Service) *pb.Service { | ||||||
|  | 	var endpoints []*pb.Endpoint | ||||||
|  | 	for _, ep := range s.Endpoints { | ||||||
|  | 		var request, response *pb.Value | ||||||
|  |  | ||||||
|  | 		if ep.Request != nil { | ||||||
|  | 			request = &pb.Value{ | ||||||
|  | 				Name:   ep.Request.Name, | ||||||
|  | 				Type:   ep.Request.Type, | ||||||
|  | 				Values: values(ep.Request.Values), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ep.Response != nil { | ||||||
|  | 			response = &pb.Value{ | ||||||
|  | 				Name:   ep.Response.Name, | ||||||
|  | 				Type:   ep.Response.Type, | ||||||
|  | 				Values: values(ep.Response.Values), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		endpoints = append(endpoints, &pb.Endpoint{ | ||||||
|  | 			Name:     ep.Name, | ||||||
|  | 			Request:  request, | ||||||
|  | 			Response: response, | ||||||
|  | 			Metadata: ep.Metadata, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var nodes []*pb.Node | ||||||
|  |  | ||||||
|  | 	for _, node := range s.Nodes { | ||||||
|  | 		nodes = append(nodes, &pb.Node{ | ||||||
|  | 			Id:       node.Id, | ||||||
|  | 			Address:  node.Address, | ||||||
|  | 			Metadata: node.Metadata, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &pb.Service{ | ||||||
|  | 		Name:      s.Name, | ||||||
|  | 		Version:   s.Version, | ||||||
|  | 		Metadata:  s.Metadata, | ||||||
|  | 		Endpoints: endpoints, | ||||||
|  | 		Nodes:     nodes, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ToService(s *pb.Service) *registry.Service { | ||||||
|  | 	var endpoints []*registry.Endpoint | ||||||
|  | 	for _, ep := range s.Endpoints { | ||||||
|  | 		var request, response *registry.Value | ||||||
|  |  | ||||||
|  | 		if ep.Request != nil { | ||||||
|  | 			request = ®istry.Value{ | ||||||
|  | 				Name:   ep.Request.Name, | ||||||
|  | 				Type:   ep.Request.Type, | ||||||
|  | 				Values: toValues(ep.Request.Values), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ep.Response != nil { | ||||||
|  | 			response = ®istry.Value{ | ||||||
|  | 				Name:   ep.Response.Name, | ||||||
|  | 				Type:   ep.Response.Type, | ||||||
|  | 				Values: toValues(ep.Response.Values), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		endpoints = append(endpoints, ®istry.Endpoint{ | ||||||
|  | 			Name:     ep.Name, | ||||||
|  | 			Request:  request, | ||||||
|  | 			Response: response, | ||||||
|  | 			Metadata: ep.Metadata, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var nodes []*registry.Node | ||||||
|  | 	for _, node := range s.Nodes { | ||||||
|  | 		nodes = append(nodes, ®istry.Node{ | ||||||
|  | 			Id:       node.Id, | ||||||
|  | 			Address:  node.Address, | ||||||
|  | 			Metadata: node.Metadata, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ®istry.Service{ | ||||||
|  | 		Name:      s.Name, | ||||||
|  | 		Version:   s.Version, | ||||||
|  | 		Metadata:  s.Metadata, | ||||||
|  | 		Endpoints: endpoints, | ||||||
|  | 		Nodes:     nodes, | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								registry/service/watcher.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								registry/service/watcher.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | package service | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	pb "github.com/micro/go-micro/registry/proto" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type serviceWatcher struct { | ||||||
|  | 	stream pb.Registry_WatchService | ||||||
|  | 	closed chan bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceWatcher) Next() (*registry.Result, error) { | ||||||
|  | 	for { | ||||||
|  | 		// check if closed | ||||||
|  | 		select { | ||||||
|  | 		case <-s.closed: | ||||||
|  | 			return nil, registry.ErrWatcherStopped | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		r, err := s.stream.Recv() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return ®istry.Result{ | ||||||
|  | 			Action:  r.Action, | ||||||
|  | 			Service: ToService(r.Service), | ||||||
|  | 		}, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *serviceWatcher) Stop() { | ||||||
|  | 	select { | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return | ||||||
|  | 	default: | ||||||
|  | 		close(s.closed) | ||||||
|  | 		s.stream.Close() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newWatcher(stream pb.Registry_WatchService) registry.Watcher { | ||||||
|  | 	return &serviceWatcher{ | ||||||
|  | 		stream: stream, | ||||||
|  | 		closed: make(chan bool), | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -10,6 +10,7 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| 	"github.com/micro/go-micro/registry" | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	"github.com/micro/go-micro/util/log" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -43,7 +44,7 @@ var ( | |||||||
| // router implements default router | // router implements default router | ||||||
| type router struct { | type router struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	opts      Options | 	options   Options | ||||||
| 	status    Status | 	status    Status | ||||||
| 	table     *table | 	table     *table | ||||||
| 	exit      chan struct{} | 	exit      chan struct{} | ||||||
| @@ -70,7 +71,7 @@ func newRouter(opts ...Option) Router { | |||||||
| 	status := Status{Code: Stopped, Error: nil} | 	status := Status{Code: Stopped, Error: nil} | ||||||
|  |  | ||||||
| 	return &router{ | 	return &router{ | ||||||
| 		opts:        options, | 		options:     options, | ||||||
| 		status:      status, | 		status:      status, | ||||||
| 		table:       newTable(), | 		table:       newTable(), | ||||||
| 		advertWg:    &sync.WaitGroup{}, | 		advertWg:    &sync.WaitGroup{}, | ||||||
| @@ -85,7 +86,7 @@ func (r *router) Init(opts ...Option) error { | |||||||
| 	defer r.Unlock() | 	defer r.Unlock() | ||||||
|  |  | ||||||
| 	for _, o := range opts { | 	for _, o := range opts { | ||||||
| 		o(&r.opts) | 		o(&r.options) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @@ -94,10 +95,10 @@ func (r *router) Init(opts ...Option) error { | |||||||
| // Options returns router options | // Options returns router options | ||||||
| func (r *router) Options() Options { | func (r *router) Options() Options { | ||||||
| 	r.Lock() | 	r.Lock() | ||||||
| 	opts := r.opts | 	options := r.options | ||||||
| 	r.Unlock() | 	r.Unlock() | ||||||
|  |  | ||||||
| 	return opts | 	return options | ||||||
| } | } | ||||||
|  |  | ||||||
| // Table returns routing table | // Table returns routing table | ||||||
| @@ -120,6 +121,9 @@ func (r *router) manageRoute(route Route, action string) error { | |||||||
| 		if err := r.table.Delete(route); err != nil && err != ErrRouteNotFound { | 		if err := r.table.Delete(route); err != nil && err != ErrRouteNotFound { | ||||||
| 			return fmt.Errorf("failed deleting route for service %s: %s", route.Service, err) | 			return fmt.Errorf("failed deleting route for service %s: %s", route.Service, err) | ||||||
| 		} | 		} | ||||||
|  | 	case "solicit": | ||||||
|  | 		// nothing to do here | ||||||
|  | 		return nil | ||||||
| 	default: | 	default: | ||||||
| 		return fmt.Errorf("failed to manage route for service %s. Unknown action: %s", route.Service, action) | 		return fmt.Errorf("failed to manage route for service %s. Unknown action: %s", route.Service, action) | ||||||
| 	} | 	} | ||||||
| @@ -139,7 +143,8 @@ func (r *router) manageServiceRoutes(service *registry.Service, action string) e | |||||||
| 			Service: service.Name, | 			Service: service.Name, | ||||||
| 			Address: node.Address, | 			Address: node.Address, | ||||||
| 			Gateway: "", | 			Gateway: "", | ||||||
| 			Network: r.opts.Network, | 			Network: r.options.Network, | ||||||
|  | 			Router:  r.options.Id, | ||||||
| 			Link:    DefaultLink, | 			Link:    DefaultLink, | ||||||
| 			Metric:  DefaultLocalMetric, | 			Metric:  DefaultLocalMetric, | ||||||
| 		} | 		} | ||||||
| @@ -278,13 +283,14 @@ func (r *router) publishAdvert(advType AdvertType, events []*Event) { | |||||||
| 	defer r.advertWg.Done() | 	defer r.advertWg.Done() | ||||||
|  |  | ||||||
| 	a := &Advert{ | 	a := &Advert{ | ||||||
| 		Id:        r.opts.Id, | 		Id:        r.options.Id, | ||||||
| 		Type:      advType, | 		Type:      advType, | ||||||
| 		TTL:       DefaultAdvertTTL, | 		TTL:       DefaultAdvertTTL, | ||||||
| 		Timestamp: time.Now(), | 		Timestamp: time.Now(), | ||||||
| 		Events:    events, | 		Events:    events, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	log.Debugf("Router publishing advert; %+v", a) | ||||||
| 	r.RLock() | 	r.RLock() | ||||||
| 	for _, sub := range r.subscribers { | 	for _, sub := range r.subscribers { | ||||||
| 		// check the exit chan first | 		// check the exit chan first | ||||||
| @@ -529,20 +535,22 @@ func (r *router) Start() error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// add all local service routes into the routing table | 	// add all local service routes into the routing table | ||||||
| 	if err := r.manageRegistryRoutes(r.opts.Registry, "create"); err != nil { | 	if err := r.manageRegistryRoutes(r.options.Registry, "create"); err != nil { | ||||||
| 		e := fmt.Errorf("failed adding registry routes: %s", err) | 		e := fmt.Errorf("failed adding registry routes: %s", err) | ||||||
| 		r.status = Status{Code: Error, Error: e} | 		r.status = Status{Code: Error, Error: e} | ||||||
| 		return e | 		return e | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// add default gateway into routing table | 	// add default gateway into routing table | ||||||
| 	if r.opts.Gateway != "" { | 	if r.options.Gateway != "" { | ||||||
| 		// note, the only non-default value is the gateway | 		// note, the only non-default value is the gateway | ||||||
| 		route := Route{ | 		route := Route{ | ||||||
| 			Service: "*", | 			Service: "*", | ||||||
| 			Address: "*", | 			Address: "*", | ||||||
| 			Gateway: r.opts.Gateway, | 			Gateway: r.options.Gateway, | ||||||
| 			Network: "*", | 			Network: "*", | ||||||
|  | 			Router:  r.options.Id, | ||||||
|  | 			Link:    DefaultLink, | ||||||
| 			Metric:  DefaultLocalMetric, | 			Metric:  DefaultLocalMetric, | ||||||
| 		} | 		} | ||||||
| 		if err := r.table.Create(route); err != nil { | 		if err := r.table.Create(route); err != nil { | ||||||
| @@ -557,7 +565,7 @@ func (r *router) Start() error { | |||||||
| 	r.exit = make(chan struct{}) | 	r.exit = make(chan struct{}) | ||||||
|  |  | ||||||
| 	// registry watcher | 	// registry watcher | ||||||
| 	regWatcher, err := r.opts.Registry.Watch() | 	regWatcher, err := r.options.Registry.Watch() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e := fmt.Errorf("failed creating registry watcher: %v", err) | 		e := fmt.Errorf("failed creating registry watcher: %v", err) | ||||||
| 		r.status = Status{Code: Error, Error: e} | 		r.status = Status{Code: Error, Error: e} | ||||||
| @@ -595,25 +603,14 @@ func (r *router) Advertise() (<-chan *Advert, error) { | |||||||
|  |  | ||||||
| 	switch r.status.Code { | 	switch r.status.Code { | ||||||
| 	case Advertising: | 	case Advertising: | ||||||
| 		advertChan := make(chan *Advert) | 		advertChan := make(chan *Advert, 128) | ||||||
| 		r.subscribers[uuid.New().String()] = advertChan | 		r.subscribers[uuid.New().String()] = advertChan | ||||||
| 		return advertChan, nil | 		return advertChan, nil | ||||||
| 	case Running: | 	case Running: | ||||||
| 		// list routing table routes to announce | 		// list all the routes and pack them into even slice to advertise | ||||||
| 		routes, err := r.table.List() | 		events, err := r.flushRouteEvents(Create) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("failed listing routes: %s", err) | 			return nil, fmt.Errorf("failed to flush routes: %s", err) | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// collect all the added routes before we attempt to add default gateway |  | ||||||
| 		events := make([]*Event, len(routes)) |  | ||||||
| 		for i, route := range routes { |  | ||||||
| 			event := &Event{ |  | ||||||
| 				Type:      Create, |  | ||||||
| 				Timestamp: time.Now(), |  | ||||||
| 				Route:     route, |  | ||||||
| 			} |  | ||||||
| 			events[i] = event |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// create event channels | 		// create event channels | ||||||
| @@ -646,7 +643,7 @@ func (r *router) Advertise() (<-chan *Advert, error) { | |||||||
| 		r.status = Status{Code: Advertising, Error: nil} | 		r.status = Status{Code: Advertising, Error: nil} | ||||||
|  |  | ||||||
| 		// create advert channel | 		// create advert channel | ||||||
| 		advertChan := make(chan *Advert) | 		advertChan := make(chan *Advert, 128) | ||||||
| 		r.subscribers[uuid.New().String()] = advertChan | 		r.subscribers[uuid.New().String()] = advertChan | ||||||
|  |  | ||||||
| 		return advertChan, nil | 		return advertChan, nil | ||||||
| @@ -669,6 +666,10 @@ func (r *router) Process(a *Advert) error { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	for _, event := range events { | 	for _, event := range events { | ||||||
|  | 		// skip if the router is the origin of this route | ||||||
|  | 		if event.Route.Router == r.options.Id { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		// create a copy of the route | 		// create a copy of the route | ||||||
| 		route := event.Route | 		route := event.Route | ||||||
| 		action := event.Type | 		action := event.Type | ||||||
| @@ -680,6 +681,43 @@ func (r *router) Process(a *Advert) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // flushRouteEvents returns a slice of events, one per each route in the routing table | ||||||
|  | func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { | ||||||
|  | 	// list all routes | ||||||
|  | 	routes, err := r.table.List() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed listing routes: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// build a list of events to advertise | ||||||
|  | 	events := make([]*Event, len(routes)) | ||||||
|  | 	for i, route := range routes { | ||||||
|  | 		event := &Event{ | ||||||
|  | 			Type:      evType, | ||||||
|  | 			Timestamp: time.Now(), | ||||||
|  | 			Route:     route, | ||||||
|  | 		} | ||||||
|  | 		events[i] = event | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return events, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Solicit advertises all of its routes to the network | ||||||
|  | // It returns error if the router fails to list the routes | ||||||
|  | func (r *router) Solicit() error { | ||||||
|  | 	events, err := r.flushRouteEvents(Update) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed solicit routes: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// advertise the routes | ||||||
|  | 	r.advertWg.Add(1) | ||||||
|  | 	go r.publishAdvert(RouteUpdate, events) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Lookup routes in the routing table | // Lookup routes in the routing table | ||||||
| func (r *router) Lookup(q Query) ([]Route, error) { | func (r *router) Lookup(q Query) ([]Route, error) { | ||||||
| 	return r.table.Query(q) | 	return r.table.Query(q) | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.Loo | |||||||
| 			Address: route.Address, | 			Address: route.Address, | ||||||
| 			Gateway: route.Gateway, | 			Gateway: route.Gateway, | ||||||
| 			Network: route.Network, | 			Network: route.Network, | ||||||
|  | 			Router:  route.Router, | ||||||
| 			Link:    route.Link, | 			Link:    route.Link, | ||||||
| 			Metric:  int64(route.Metric), | 			Metric:  int64(route.Metric), | ||||||
| 		} | 		} | ||||||
| @@ -58,6 +59,7 @@ func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Route | |||||||
| 				Address: event.Route.Address, | 				Address: event.Route.Address, | ||||||
| 				Gateway: event.Route.Gateway, | 				Gateway: event.Route.Gateway, | ||||||
| 				Network: event.Route.Network, | 				Network: event.Route.Network, | ||||||
|  | 				Router:  event.Route.Router, | ||||||
| 				Link:    event.Route.Link, | 				Link:    event.Route.Link, | ||||||
| 				Metric:  int64(event.Route.Metric), | 				Metric:  int64(event.Route.Metric), | ||||||
| 			} | 			} | ||||||
| @@ -97,6 +99,7 @@ func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessRes | |||||||
| 			Address: event.Route.Address, | 			Address: event.Route.Address, | ||||||
| 			Gateway: event.Route.Gateway, | 			Gateway: event.Route.Gateway, | ||||||
| 			Network: event.Route.Network, | 			Network: event.Route.Network, | ||||||
|  | 			Router:  event.Route.Router, | ||||||
| 			Link:    event.Route.Link, | 			Link:    event.Route.Link, | ||||||
| 			Metric:  int(event.Route.Metric), | 			Metric:  int(event.Route.Metric), | ||||||
| 		} | 		} | ||||||
| @@ -161,6 +164,7 @@ func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Rout | |||||||
| 			Address: event.Route.Address, | 			Address: event.Route.Address, | ||||||
| 			Gateway: event.Route.Gateway, | 			Gateway: event.Route.Gateway, | ||||||
| 			Network: event.Route.Network, | 			Network: event.Route.Network, | ||||||
|  | 			Router:  event.Route.Router, | ||||||
| 			Link:    event.Route.Link, | 			Link:    event.Route.Link, | ||||||
| 			Metric:  int64(event.Route.Metric), | 			Metric:  int64(event.Route.Metric), | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ func (t *Table) Create(ctx context.Context, route *pb.Route, resp *pb.CreateResp | |||||||
| 		Address: route.Address, | 		Address: route.Address, | ||||||
| 		Gateway: route.Gateway, | 		Gateway: route.Gateway, | ||||||
| 		Network: route.Network, | 		Network: route.Network, | ||||||
|  | 		Router:  route.Router, | ||||||
| 		Link:    route.Link, | 		Link:    route.Link, | ||||||
| 		Metric:  int(route.Metric), | 		Metric:  int(route.Metric), | ||||||
| 	}) | 	}) | ||||||
| @@ -34,6 +35,7 @@ func (t *Table) Update(ctx context.Context, route *pb.Route, resp *pb.UpdateResp | |||||||
| 		Address: route.Address, | 		Address: route.Address, | ||||||
| 		Gateway: route.Gateway, | 		Gateway: route.Gateway, | ||||||
| 		Network: route.Network, | 		Network: route.Network, | ||||||
|  | 		Router:  route.Router, | ||||||
| 		Link:    route.Link, | 		Link:    route.Link, | ||||||
| 		Metric:  int(route.Metric), | 		Metric:  int(route.Metric), | ||||||
| 	}) | 	}) | ||||||
| @@ -50,6 +52,7 @@ func (t *Table) Delete(ctx context.Context, route *pb.Route, resp *pb.DeleteResp | |||||||
| 		Address: route.Address, | 		Address: route.Address, | ||||||
| 		Gateway: route.Gateway, | 		Gateway: route.Gateway, | ||||||
| 		Network: route.Network, | 		Network: route.Network, | ||||||
|  | 		Router:  route.Router, | ||||||
| 		Link:    route.Link, | 		Link:    route.Link, | ||||||
| 		Metric:  int(route.Metric), | 		Metric:  int(route.Metric), | ||||||
| 	}) | 	}) | ||||||
| @@ -74,6 +77,7 @@ func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse | |||||||
| 			Address: route.Address, | 			Address: route.Address, | ||||||
| 			Gateway: route.Gateway, | 			Gateway: route.Gateway, | ||||||
| 			Network: route.Network, | 			Network: route.Network, | ||||||
|  | 			Router:  route.Router, | ||||||
| 			Link:    route.Link, | 			Link:    route.Link, | ||||||
| 			Metric:  int64(route.Metric), | 			Metric:  int64(route.Metric), | ||||||
| 		} | 		} | ||||||
| @@ -102,6 +106,7 @@ func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryR | |||||||
| 			Address: route.Address, | 			Address: route.Address, | ||||||
| 			Gateway: route.Gateway, | 			Gateway: route.Gateway, | ||||||
| 			Network: route.Network, | 			Network: route.Network, | ||||||
|  | 			Router:  route.Router, | ||||||
| 			Link:    route.Link, | 			Link:    route.Link, | ||||||
| 			Metric:  int64(route.Metric), | 			Metric:  int64(route.Metric), | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -672,10 +672,12 @@ type Route struct { | |||||||
| 	Gateway string `protobuf:"bytes,3,opt,name=gateway,proto3" json:"gateway,omitempty"` | 	Gateway string `protobuf:"bytes,3,opt,name=gateway,proto3" json:"gateway,omitempty"` | ||||||
| 	// the network for this destination | 	// the network for this destination | ||||||
| 	Network string `protobuf:"bytes,4,opt,name=network,proto3" json:"network,omitempty"` | 	Network string `protobuf:"bytes,4,opt,name=network,proto3" json:"network,omitempty"` | ||||||
|  | 	// router if the router id | ||||||
|  | 	Router string `protobuf:"bytes,5,opt,name=router,proto3" json:"router,omitempty"` | ||||||
| 	// the network link | 	// the network link | ||||||
| 	Link string `protobuf:"bytes,5,opt,name=link,proto3" json:"link,omitempty"` | 	Link string `protobuf:"bytes,6,opt,name=link,proto3" json:"link,omitempty"` | ||||||
| 	// the metric / score of this route | 	// the metric / score of this route | ||||||
| 	Metric               int64    `protobuf:"varint,6,opt,name=metric,proto3" json:"metric,omitempty"` | 	Metric               int64    `protobuf:"varint,7,opt,name=metric,proto3" json:"metric,omitempty"` | ||||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
| 	XXX_unrecognized     []byte   `json:"-"` | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
| 	XXX_sizecache        int32    `json:"-"` | 	XXX_sizecache        int32    `json:"-"` | ||||||
| @@ -734,6 +736,13 @@ func (m *Route) GetNetwork() string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (m *Route) GetRouter() string { | ||||||
|  | 	if m != nil { | ||||||
|  | 		return m.Router | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
| func (m *Route) GetLink() string { | func (m *Route) GetLink() string { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
| 		return m.Link | 		return m.Link | ||||||
| @@ -861,51 +870,51 @@ func init() { | |||||||
| } | } | ||||||
|  |  | ||||||
| var fileDescriptor_6a36eee0b1adf739 = []byte{ | var fileDescriptor_6a36eee0b1adf739 = []byte{ | ||||||
| 	// 689 bytes of a gzipped FileDescriptorProto | 	// 699 bytes of a gzipped FileDescriptorProto | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x4e, 0xdb, 0x40, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x4e, 0xdb, 0x40, | ||||||
| 	0x10, 0xb6, 0x93, 0xd8, 0x28, 0xd3, 0x10, 0xdc, 0x51, 0x05, 0x56, 0x5a, 0x20, 0xf2, 0x29, 0x42, | 	0x10, 0xb6, 0x9d, 0xd8, 0x91, 0xa7, 0xc1, 0xb8, 0xa3, 0x0a, 0xac, 0xb4, 0x40, 0xe4, 0x53, 0x84, | ||||||
| 	0xd4, 0xa9, 0xd2, 0x6b, 0xff, 0x02, 0xa5, 0xaa, 0x54, 0x0e, 0xad, 0x0b, 0xea, 0xd9, 0xd8, 0x23, | 	0xa8, 0x53, 0xa5, 0xd7, 0xfe, 0x05, 0x4a, 0x55, 0xa9, 0x1c, 0x5a, 0x17, 0xd4, 0xb3, 0xb1, 0x57, | ||||||
| 	0x6a, 0x91, 0xd8, 0x66, 0x77, 0x03, 0xca, 0xb9, 0x8f, 0xd1, 0x27, 0xe8, 0x73, 0xf5, 0xda, 0x87, | 	0xd4, 0x22, 0xb1, 0xcd, 0xee, 0x06, 0x94, 0x73, 0x9f, 0xa6, 0xe7, 0x3e, 0x52, 0xaf, 0x7d, 0x88, | ||||||
| 	0xa8, 0xbc, 0xbb, 0x0e, 0x21, 0xc6, 0x48, 0x70, 0xf2, 0xce, 0xdf, 0x37, 0xff, 0x63, 0x18, 0x4c, | 	0xca, 0xbb, 0xeb, 0x10, 0x62, 0x8c, 0x44, 0x4e, 0xde, 0x99, 0xf9, 0xe6, 0x9b, 0x99, 0xdd, 0x99, | ||||||
| 	0x93, 0x88, 0x65, 0xc3, 0xf3, 0xec, 0xa5, 0x7a, 0xb0, 0x6c, 0x26, 0x88, 0x0d, 0x73, 0x96, 0x89, | 	0x31, 0x0c, 0xa6, 0x69, 0x4c, 0xf3, 0xe1, 0x45, 0xfe, 0x52, 0x1e, 0x68, 0x3e, 0xe3, 0x84, 0x0e, | ||||||
| 	0x92, 0xf0, 0x25, 0x81, 0x1b, 0xe7, 0x99, 0x2f, 0x75, 0x7c, 0xc5, 0xf6, 0xda, 0xb0, 0x16, 0xd0, | 	0x0b, 0x9a, 0xf3, 0x4a, 0x08, 0x84, 0x80, 0x9b, 0x17, 0x79, 0x20, 0x30, 0x81, 0x54, 0xfb, 0x36, | ||||||
| 	0xe5, 0x8c, 0xb8, 0xf0, 0xde, 0x41, 0xe7, 0x38, 0xe1, 0x22, 0x20, 0x9e, 0x67, 0x29, 0x27, 0xf4, | 	0x74, 0x42, 0x72, 0x35, 0x23, 0x8c, 0xfb, 0xef, 0xa0, 0x7b, 0x92, 0x32, 0x1e, 0x12, 0x56, 0xe4, | ||||||
| 	0xc1, 0x96, 0x4a, 0xdc, 0x35, 0xfb, 0xcd, 0xc1, 0x93, 0xd1, 0xa6, 0xbf, 0x62, 0xec, 0x07, 0xc5, | 	0x19, 0x23, 0x18, 0x80, 0x25, 0x40, 0xcc, 0xd3, 0xfb, 0xad, 0xc1, 0x93, 0xd1, 0x56, 0xb0, 0xe2, | ||||||
| 	0x27, 0xd0, 0x5a, 0xde, 0x5b, 0x58, 0x3f, 0xce, 0xb2, 0x8b, 0x59, 0xae, 0x01, 0x71, 0x1f, 0xac, | 	0x1c, 0x84, 0xe5, 0x27, 0x54, 0x28, 0xff, 0x2d, 0x6c, 0x9c, 0xe4, 0xf9, 0xe5, 0xac, 0x50, 0x84, | ||||||
| 	0xcb, 0x19, 0xb1, 0xb9, 0x6b, 0xf6, 0xcd, 0x3b, 0xed, 0xbf, 0x15, 0xd2, 0x40, 0x29, 0x79, 0x1f, | 	0x78, 0x00, 0xe6, 0xd5, 0x8c, 0xd0, 0xb9, 0xa7, 0xf7, 0xf5, 0x7b, 0xfd, 0xbf, 0x95, 0xd6, 0x50, | ||||||
| 	0xa0, 0x5b, 0x9a, 0x3f, 0x32, 0x80, 0x37, 0xd0, 0x51, 0x88, 0x8f, 0xf2, 0xff, 0x1e, 0xd6, 0xb5, | 	0x82, 0xfc, 0x0f, 0xe0, 0x54, 0xee, 0x6b, 0x26, 0xf0, 0x06, 0xba, 0x92, 0x71, 0xad, 0xf8, 0xef, | ||||||
| 	0xf5, 0x23, 0xdd, 0x77, 0xa1, 0xf3, 0x23, 0x14, 0xd1, 0xcf, 0xb2, 0x9e, 0x7f, 0x4c, 0xb0, 0xc7, | 	0x61, 0x43, 0x79, 0xaf, 0x19, 0xde, 0x81, 0xee, 0x8f, 0x88, 0xc7, 0x3f, 0xab, 0xfb, 0xfc, 0xad, | ||||||
| 	0xf1, 0x15, 0x31, 0x81, 0x5d, 0x68, 0x24, 0xb1, 0x0c, 0xa3, 0x1d, 0x34, 0x92, 0x18, 0x87, 0xd0, | 	0x83, 0x35, 0x4e, 0xae, 0x09, 0xe5, 0xe8, 0x80, 0x91, 0x26, 0x22, 0x0d, 0x3b, 0x34, 0xd2, 0x04, | ||||||
| 	0x12, 0xf3, 0x9c, 0xdc, 0x46, 0xdf, 0x1c, 0x74, 0x47, 0xcf, 0x2b, 0xc0, 0xca, 0xec, 0x64, 0x9e, | 	0x87, 0xd0, 0xe6, 0xf3, 0x82, 0x78, 0x46, 0x5f, 0x1f, 0x38, 0xa3, 0xe7, 0x35, 0x62, 0xe9, 0x76, | ||||||
| 	0x53, 0x20, 0x15, 0xf1, 0x05, 0xb4, 0x45, 0x32, 0x25, 0x2e, 0xc2, 0x69, 0xee, 0x36, 0xfb, 0xe6, | 	0x3a, 0x2f, 0x48, 0x28, 0x80, 0xf8, 0x02, 0x6c, 0x9e, 0x4e, 0x09, 0xe3, 0xd1, 0xb4, 0xf0, 0x5a, | ||||||
| 	0xa0, 0x19, 0xdc, 0x30, 0xd0, 0x81, 0xa6, 0x10, 0x13, 0xb7, 0x25, 0xf9, 0xc5, 0xb3, 0x88, 0x9d, | 	0x7d, 0x7d, 0xd0, 0x0a, 0x6f, 0x15, 0xe8, 0x42, 0x8b, 0xf3, 0x89, 0xd7, 0x16, 0xfa, 0xf2, 0x58, | ||||||
| 	0xae, 0x28, 0x15, 0xdc, 0xb5, 0x6a, 0x62, 0x3f, 0x2a, 0xc4, 0x81, 0xd6, 0xf2, 0x9e, 0xc2, 0xc6, | 	0xe6, 0x4e, 0xae, 0x49, 0xc6, 0x99, 0x67, 0x36, 0xe4, 0x7e, 0x5c, 0x9a, 0x43, 0x85, 0xf2, 0x9f, | ||||||
| 	0x57, 0x96, 0x45, 0xc4, 0x79, 0x99, 0xbe, 0xe7, 0x40, 0xf7, 0x90, 0x51, 0x28, 0x68, 0x99, 0xf3, | 	0xc2, 0xe6, 0x57, 0x9a, 0xc7, 0x84, 0xb1, 0xaa, 0x7c, 0xdf, 0x05, 0xe7, 0x88, 0x92, 0x88, 0x93, | ||||||
| 	0x91, 0x26, 0x74, 0x9b, 0x73, 0x9a, 0xc7, 0xcb, 0x3a, 0xbf, 0x4c, 0xb0, 0x24, 0x34, 0xfa, 0x3a, | 	0x65, 0xcd, 0x47, 0x32, 0x21, 0x77, 0x35, 0x67, 0x45, 0xb2, 0x8c, 0xf9, 0xa5, 0x83, 0x29, 0xa8, | ||||||
| 	0x47, 0x53, 0xe6, 0xd8, 0xbb, 0x3b, 0x80, 0xba, 0x14, 0x1b, 0xab, 0x29, 0xee, 0x83, 0x25, 0xed, | 	0x31, 0x50, 0x35, 0xea, 0xa2, 0xc6, 0xde, 0xfd, 0x09, 0x34, 0x95, 0x68, 0xac, 0x96, 0x78, 0x00, | ||||||
| 	0x64, 0xf2, 0xf5, 0xbd, 0x50, 0x4a, 0xde, 0x29, 0x58, 0xb2, 0x97, 0xe8, 0xc2, 0x1a, 0x27, 0x76, | 	0xa6, 0xf0, 0x13, 0xc5, 0x37, 0xbf, 0x85, 0x04, 0xf9, 0x67, 0x60, 0x8a, 0xb7, 0x44, 0x0f, 0x3a, | ||||||
| 	0x95, 0x44, 0xa4, 0xab, 0x5f, 0x92, 0x85, 0xe4, 0x3c, 0x14, 0x74, 0x1d, 0xce, 0xa5, 0xb3, 0x76, | 	0x8c, 0xd0, 0xeb, 0x34, 0x26, 0xea, 0xf6, 0x2b, 0xb1, 0xb4, 0x5c, 0x44, 0x9c, 0xdc, 0x44, 0x73, | ||||||
| 	0x50, 0x92, 0x85, 0x24, 0x25, 0x71, 0x9d, 0xb1, 0x0b, 0xe9, 0xac, 0x1d, 0x94, 0xa4, 0xf7, 0xdb, | 	0x11, 0xcc, 0x0e, 0x2b, 0xb1, 0xb4, 0x64, 0x84, 0xdf, 0xe4, 0xf4, 0x52, 0x04, 0xb3, 0xc3, 0x4a, | ||||||
| 	0x04, 0x4b, 0xfa, 0xb9, 0x1f, 0x37, 0x8c, 0x63, 0x46, 0x9c, 0x97, 0xb8, 0x9a, 0x5c, 0xf6, 0xd8, | 	0xf4, 0xff, 0xe8, 0x60, 0x8a, 0x38, 0x0f, 0xf3, 0x46, 0x49, 0x42, 0x09, 0x63, 0x15, 0xaf, 0x12, | ||||||
| 	0xac, 0xf5, 0xd8, 0xba, 0xe5, 0x11, 0x11, 0x5a, 0x93, 0x24, 0xbd, 0x70, 0x2d, 0xc9, 0x96, 0x6f, | 	0x97, 0x23, 0xb6, 0x1a, 0x23, 0xb6, 0xef, 0x44, 0xc4, 0x2d, 0xd5, 0x83, 0xd4, 0x33, 0x85, 0x41, | ||||||
| 	0xdc, 0x04, 0x7b, 0x4a, 0x82, 0x25, 0x91, 0x6b, 0xcb, 0x2a, 0x69, 0xca, 0x1b, 0x81, 0xfd, 0x5d, | 	0x49, 0x88, 0xd0, 0x9e, 0xa4, 0xd9, 0xa5, 0x67, 0x09, 0xad, 0x38, 0x97, 0xd8, 0x29, 0xe1, 0x34, | ||||||
| 	0x84, 0x62, 0xc6, 0x0b, 0xab, 0x28, 0x8b, 0xcb, 0xd0, 0xe4, 0x1b, 0x9f, 0x81, 0x45, 0x8c, 0x65, | 	0x8d, 0xbd, 0x8e, 0xb8, 0x3d, 0x25, 0xf9, 0x23, 0xb0, 0xbe, 0xf3, 0x88, 0xcf, 0x58, 0xe9, 0x15, | ||||||
| 	0x4c, 0x47, 0xa5, 0x08, 0x6f, 0x0c, 0x5d, 0x65, 0xb3, 0x98, 0xfa, 0x21, 0xd8, 0x5c, 0x72, 0xf4, | 	0xe7, 0x49, 0x95, 0xb2, 0x38, 0xe3, 0x33, 0x30, 0x09, 0xa5, 0x39, 0x55, 0xd9, 0x4a, 0xc1, 0x1f, | ||||||
| 	0xd6, 0x6c, 0x55, 0x2a, 0xad, 0x0d, 0xb4, 0xda, 0xde, 0x08, 0xe0, 0x66, 0x5c, 0x11, 0xa1, 0xab, | 	0x83, 0x23, 0x7d, 0x16, 0xd3, 0x30, 0x04, 0x8b, 0x09, 0x8d, 0x9a, 0xa6, 0xed, 0xda, 0x0b, 0x28, | ||||||
| 	0xa8, 0x71, 0x9a, 0x66, 0xb3, 0x34, 0x22, 0xc7, 0x40, 0x07, 0x3a, 0x8a, 0xa7, 0x66, 0xc5, 0x31, | 	0x07, 0x05, 0xdb, 0x1f, 0x01, 0xdc, 0xb6, 0x31, 0x22, 0x38, 0x52, 0x1a, 0x67, 0x59, 0x3e, 0xcb, | ||||||
| 	0xf7, 0x86, 0xd0, 0x5e, 0xb4, 0x1f, 0x01, 0x6c, 0x35, 0x68, 0x8e, 0x51, 0xbc, 0xd5, 0x88, 0x39, | 	0x62, 0xe2, 0x6a, 0xe8, 0x42, 0x57, 0xea, 0x64, 0x0f, 0xb9, 0xfa, 0xfe, 0x10, 0xec, 0x45, 0x5b, | ||||||
| 	0x66, 0xf1, 0xd6, 0x06, 0x8d, 0xd1, 0xbf, 0x06, 0xd8, 0xb2, 0xf2, 0x0c, 0xbf, 0x80, 0xad, 0xee, | 	0x20, 0x80, 0x25, 0x1b, 0xd0, 0xd5, 0xca, 0xb3, 0x6c, 0x3d, 0x57, 0x2f, 0xcf, 0xca, 0xc1, 0x18, | ||||||
| 	0x04, 0xee, 0x54, 0x42, 0xbb, 0x75, 0x7f, 0x7a, 0xbb, 0xb5, 0x72, 0x3d, 0xac, 0x06, 0x1e, 0x80, | 	0xfd, 0x33, 0xc0, 0x0a, 0xe5, 0x95, 0x7c, 0x01, 0x4b, 0xee, 0x0f, 0xdc, 0xad, 0xa5, 0x76, 0x67, | ||||||
| 	0x25, 0x77, 0x16, 0xb7, 0x2b, 0xba, 0xcb, 0xbb, 0xdc, 0xab, 0xd9, 0x1f, 0xcf, 0x78, 0x65, 0xe2, | 	0x2f, 0xf5, 0xf6, 0x1a, 0xed, 0xaa, 0x89, 0x35, 0x3c, 0x04, 0x53, 0xcc, 0x32, 0xee, 0xd4, 0xb0, | ||||||
| 	0x01, 0xb4, 0x55, 0x7a, 0x09, 0x27, 0x74, 0xab, 0x83, 0xa9, 0x21, 0xb6, 0x6a, 0xb6, 0x5c, 0x62, | 	0xcb, 0x33, 0xde, 0x6b, 0x98, 0x2b, 0x5f, 0x7b, 0xa5, 0xe3, 0x21, 0xd8, 0xb2, 0xbc, 0x94, 0x11, | ||||||
| 	0x7c, 0x82, 0x35, 0xbd, 0x7f, 0x58, 0xa7, 0xd7, 0xeb, 0x57, 0x04, 0xab, 0x2b, 0x6b, 0xe0, 0xd1, | 	0xf4, 0xea, 0x0d, 0xab, 0x28, 0xb6, 0x1b, 0xa6, 0x5f, 0x70, 0x7c, 0x82, 0x8e, 0x9a, 0x4b, 0x6c, | ||||||
| 	0x62, 0x06, 0xea, 0x03, 0xd9, 0xad, 0xeb, 0xe8, 0x02, 0x66, 0xf4, 0xb7, 0x01, 0xd6, 0x49, 0x78, | 	0xc2, 0xf5, 0xfa, 0x35, 0xc3, 0xea, 0x28, 0x6b, 0x78, 0xbc, 0xe8, 0x81, 0xe6, 0x44, 0xf6, 0x9a, | ||||||
| 	0x36, 0x21, 0x3c, 0x2c, 0x9b, 0x83, 0x35, 0x2b, 0x77, 0x07, 0xdc, 0xca, 0xd9, 0x30, 0x0a, 0x10, | 	0x5e, 0x74, 0x41, 0x33, 0xfa, 0x6b, 0x80, 0x79, 0x1a, 0x9d, 0x4f, 0x08, 0x1e, 0x55, 0x8f, 0x83, | ||||||
| 	0xd5, 0xd5, 0x07, 0x80, 0xac, 0x5c, 0x1a, 0x09, 0xa2, 0xc6, 0xe1, 0x01, 0x20, 0x2b, 0xc7, 0xc9, | 	0x0d, 0xa3, 0x78, 0x0f, 0xdd, 0xca, 0x3a, 0xd1, 0x4a, 0x12, 0xf9, 0xaa, 0x8f, 0x20, 0x59, 0xd9, | ||||||
| 	0xc0, 0x31, 0xb4, 0x8a, 0x7f, 0xdc, 0x3d, 0xd5, 0xa9, 0x0e, 0xc2, 0xf2, 0x4f, 0xd1, 0x33, 0xf0, | 	0x40, 0x82, 0x44, 0xb6, 0xc3, 0x23, 0x48, 0x56, 0x96, 0x96, 0x86, 0x63, 0x68, 0x97, 0xff, 0xbe, | ||||||
| 	0x73, 0x79, 0x5b, 0xb6, 0x6b, 0xfe, 0x27, 0x1a, 0x68, 0xa7, 0x4e, 0x5c, 0x22, 0x9d, 0xd9, 0xf2, | 	0x07, 0x6e, 0xa7, 0xde, 0x08, 0xcb, 0x3f, 0x4b, 0x5f, 0xc3, 0xcf, 0xd5, 0xce, 0xd9, 0x69, 0xf8, | ||||||
| 	0x9f, 0xfc, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0xd0, 0xc0, 0x27, 0xbf, 0x07, 0x00, | 	0xcf, 0x28, 0xa2, 0xdd, 0x26, 0x73, 0xc5, 0x74, 0x6e, 0x89, 0x7f, 0xf5, 0xeb, 0xff, 0x01, 0x00, | ||||||
| 	0x00, | 	0x00, 0xff, 0xff, 0xe2, 0xe9, 0xe2, 0x3b, 0xd7, 0x07, 0x00, 0x00, | ||||||
| } | } | ||||||
|  |  | ||||||
| // Reference imports to suppress errors if they are not otherwise used. | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ service Router { | |||||||
| 	rpc Lookup(LookupRequest) returns (LookupResponse) {}; | 	rpc Lookup(LookupRequest) returns (LookupResponse) {}; | ||||||
|         rpc Watch(WatchRequest) returns (stream Event) {}; |         rpc Watch(WatchRequest) returns (stream Event) {}; | ||||||
|         rpc Advertise(Request) returns (stream Advert) {}; |         rpc Advertise(Request) returns (stream Advert) {}; | ||||||
|  |         rpc Solicit(Request) returns (Response) {}; | ||||||
|         rpc Process(Advert) returns (ProcessResponse) {}; |         rpc Process(Advert) returns (ProcessResponse) {}; | ||||||
| 	rpc Status(Request) returns (StatusResponse) {}; | 	rpc Status(Request) returns (StatusResponse) {}; | ||||||
| } | } | ||||||
| @@ -22,6 +23,9 @@ service Table { | |||||||
| // Empty request | // Empty request | ||||||
| message Request {} | message Request {} | ||||||
|  |  | ||||||
|  | // Empty response | ||||||
|  | message Response {} | ||||||
|  |  | ||||||
| // ListResponse is returned by List | // ListResponse is returned by List | ||||||
| message ListResponse { | message ListResponse { | ||||||
| 	repeated Route routes = 1; | 	repeated Route routes = 1; | ||||||
| @@ -37,10 +41,12 @@ message LookupResponse { | |||||||
| 	repeated Route routes = 1; | 	repeated Route routes = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // QueryRequest queries Table for Routes | ||||||
| message QueryRequest{ | message QueryRequest{ | ||||||
| 	Query query = 1; | 	Query query = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // QueryResponse is returned by Query | ||||||
| message QueryResponse { | message QueryResponse { | ||||||
| 	repeated Route routes = 1; | 	repeated Route routes = 1; | ||||||
| } | } | ||||||
| @@ -117,10 +123,12 @@ message Route { | |||||||
| 	string gateway = 3; | 	string gateway = 3; | ||||||
| 	// the network for this destination | 	// the network for this destination | ||||||
| 	string network = 4; | 	string network = 4; | ||||||
|  | 	// router if the router id | ||||||
|  | 	string router = 5; | ||||||
| 	// the network link | 	// the network link | ||||||
| 	string link = 5; | 	string link = 6; | ||||||
| 	// the metric / score of this route | 	// the metric / score of this route | ||||||
| 	int64 metric = 6; | 	int64 metric = 7; | ||||||
| } | } | ||||||
|  |  | ||||||
| message Status { | message Status { | ||||||
|   | |||||||
| @@ -11,29 +11,38 @@ type QueryOptions struct { | |||||||
| 	Gateway string | 	Gateway string | ||||||
| 	// Network is network address | 	// Network is network address | ||||||
| 	Network string | 	Network string | ||||||
|  | 	// Router is router id | ||||||
|  | 	Router string | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryService sets destination address | // QueryService sets service to query | ||||||
| func QueryService(s string) QueryOption { | func QueryService(s string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Service = s | 		o.Service = s | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryGateway sets route gateway | // QueryGateway sets gateway address to query | ||||||
| func QueryGateway(g string) QueryOption { | func QueryGateway(g string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Gateway = g | 		o.Gateway = g | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryNetwork sets route network address | // QueryNetwork sets network name to query | ||||||
| func QueryNetwork(n string) QueryOption { | func QueryNetwork(n string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Network = n | 		o.Network = n | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // QueryRouter sets router id to query | ||||||
|  | func QueryRouter(r string) QueryOption { | ||||||
|  | 	return func(o *QueryOptions) { | ||||||
|  | 		o.Router = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // Query is routing table query | // Query is routing table query | ||||||
| type Query interface { | type Query interface { | ||||||
| 	// Options returns query options | 	// Options returns query options | ||||||
| @@ -52,6 +61,7 @@ func NewQuery(opts ...QueryOption) Query { | |||||||
| 		Service: "*", | 		Service: "*", | ||||||
| 		Gateway: "*", | 		Gateway: "*", | ||||||
| 		Network: "*", | 		Network: "*", | ||||||
|  | 		Router:  "*", | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, o := range opts { | 	for _, o := range opts { | ||||||
| @@ -67,8 +77,3 @@ func NewQuery(opts ...QueryOption) Query { | |||||||
| func (q *query) Options() QueryOptions { | func (q *query) Options() QueryOptions { | ||||||
| 	return q.opts | 	return q.opts | ||||||
| } | } | ||||||
|  |  | ||||||
| // String prints routing table query in human readable form |  | ||||||
| func (q query) String() string { |  | ||||||
| 	return "query" |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -7,9 +7,9 @@ import ( | |||||||
| var ( | var ( | ||||||
| 	// DefaultLink is default network link | 	// DefaultLink is default network link | ||||||
| 	DefaultLink = "local" | 	DefaultLink = "local" | ||||||
| 	// DefaultLocalMetric is default route cost metric for the local network | 	// DefaultLocalMetric is default route cost for a local route | ||||||
| 	DefaultLocalMetric = 1 | 	DefaultLocalMetric = 1 | ||||||
| 	// DefaultNetworkMetric is default route cost metric for the micro network | 	// DefaultNetworkMetric is default route cost for a network route | ||||||
| 	DefaultNetworkMetric = 10 | 	DefaultNetworkMetric = 10 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -23,6 +23,8 @@ type Route struct { | |||||||
| 	Gateway string | 	Gateway string | ||||||
| 	// Network is network address | 	// Network is network address | ||||||
| 	Network string | 	Network string | ||||||
|  | 	// Router is router id | ||||||
|  | 	Router string | ||||||
| 	// Link is network link | 	// Link is network link | ||||||
| 	Link string | 	Link string | ||||||
| 	// Metric is the route cost metric | 	// Metric is the route cost metric | ||||||
| @@ -33,6 +35,6 @@ type Route struct { | |||||||
| func (r *Route) Hash() uint64 { | func (r *Route) Hash() uint64 { | ||||||
| 	h := fnv.New64() | 	h := fnv.New64() | ||||||
| 	h.Reset() | 	h.Reset() | ||||||
| 	h.Write([]byte(r.Service + r.Address + r.Gateway + r.Network + r.Link)) | 	h.Write([]byte(r.Service + r.Address + r.Gateway + r.Network + r.Router + r.Link)) | ||||||
| 	return h.Sum64() | 	return h.Sum64() | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,17 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// DefaultAddress is default router address | ||||||
|  | 	DefaultAddress = ":9093" | ||||||
|  | 	// DefaultName is default router service name | ||||||
|  | 	DefaultName = "go.micro.router" | ||||||
|  | 	// DefaultNetwork is default micro network | ||||||
|  | 	DefaultNetwork = "go.micro" | ||||||
|  | 	// DefaultRouter is default network router | ||||||
|  | 	DefaultRouter = NewRouter() | ||||||
|  | ) | ||||||
|  |  | ||||||
| // Router is an interface for a routing control plane | // Router is an interface for a routing control plane | ||||||
| type Router interface { | type Router interface { | ||||||
| 	// Init initializes the router with options | 	// Init initializes the router with options | ||||||
| @@ -17,6 +28,8 @@ type Router interface { | |||||||
| 	Advertise() (<-chan *Advert, error) | 	Advertise() (<-chan *Advert, error) | ||||||
| 	// Process processes incoming adverts | 	// Process processes incoming adverts | ||||||
| 	Process(*Advert) error | 	Process(*Advert) error | ||||||
|  | 	// Solicit advertises the whole routing table to the network | ||||||
|  | 	Solicit() error | ||||||
| 	// Lookup queries routes in the routing table | 	// Lookup queries routes in the routing table | ||||||
| 	Lookup(Query) ([]Route, error) | 	Lookup(Query) ([]Route, error) | ||||||
| 	// Watch returns a watcher which tracks updates to the routing table | 	// Watch returns a watcher which tracks updates to the routing table | ||||||
| @@ -31,16 +44,17 @@ type Router interface { | |||||||
| 	String() string | 	String() string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Table is an interface for routing table | ||||||
| type Table interface { | type Table interface { | ||||||
| 	// Create new route in the routing table | 	// Create new route in the routing table | ||||||
| 	Create(Route) error | 	Create(Route) error | ||||||
| 	// Delete deletes existing route from the routing table | 	// Delete existing route from the routing table | ||||||
| 	Delete(Route) error | 	Delete(Route) error | ||||||
| 	// Update updates route in the routing table | 	// Update route in the routing table | ||||||
| 	Update(Route) error | 	Update(Route) error | ||||||
| 	// List returns the list of all routes in the table | 	// List all routes in the table | ||||||
| 	List() ([]Route, error) | 	List() ([]Route, error) | ||||||
| 	// Query queries routes in the routing table | 	// Query routes in the routing table | ||||||
| 	Query(Query) ([]Route, error) | 	Query(Query) ([]Route, error) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -125,17 +139,6 @@ type Advert struct { | |||||||
| 	Events []*Event | 	Events []*Event | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// DefaultAddress is default router address |  | ||||||
| 	DefaultAddress = ":9093" |  | ||||||
| 	// DefaultName is default router service name |  | ||||||
| 	DefaultName = "go.micro.router" |  | ||||||
| 	// DefaultNetwork is default micro network |  | ||||||
| 	DefaultNetwork = "go.micro" |  | ||||||
| 	// DefaultRouter is default network router |  | ||||||
| 	DefaultRouter = NewRouter() |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // NewRouter creates new Router and returns it | // NewRouter creates new Router and returns it | ||||||
| func NewRouter(opts ...Option) Router { | func NewRouter(opts ...Option) Router { | ||||||
| 	return newRouter(opts...) | 	return newRouter(opts...) | ||||||
|   | |||||||
| @@ -220,6 +220,42 @@ func (s *svc) Process(advert *router.Advert) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Solicit advertise all routes | ||||||
|  | func (s *svc) Solicit() error { | ||||||
|  | 	// list all the routes | ||||||
|  | 	routes, err := s.table.List() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// build events to advertise | ||||||
|  | 	events := make([]*router.Event, len(routes)) | ||||||
|  | 	for i, _ := range events { | ||||||
|  | 		events[i] = &router.Event{ | ||||||
|  | 			Type:      router.Update, | ||||||
|  | 			Timestamp: time.Now(), | ||||||
|  | 			Route:     routes[i], | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	advert := &router.Advert{ | ||||||
|  | 		Id:        s.opts.Id, | ||||||
|  | 		Type:      router.RouteUpdate, | ||||||
|  | 		Timestamp: time.Now(), | ||||||
|  | 		TTL:       time.Duration(router.DefaultAdvertTTL), | ||||||
|  | 		Events:    events, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case s.advertChan <- advert: | ||||||
|  | 	case <-s.exit: | ||||||
|  | 		close(s.advertChan) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Status returns router status | // Status returns router status | ||||||
| func (s *svc) Status() router.Status { | func (s *svc) Status() router.Status { | ||||||
| 	s.Lock() | 	s.Lock() | ||||||
|   | |||||||
| @@ -8,7 +8,14 @@ import ( | |||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // table is an in memory routing table | var ( | ||||||
|  | 	// ErrRouteNotFound is returned when no route was found in the routing table | ||||||
|  | 	ErrRouteNotFound = errors.New("route not found") | ||||||
|  | 	// ErrDuplicateRoute is returned when the route already exists | ||||||
|  | 	ErrDuplicateRoute = errors.New("duplicate route") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // table is an in-memory routing table | ||||||
| type table struct { | type table struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	// routes stores service routes | 	// routes stores service routes | ||||||
| @@ -25,6 +32,19 @@ func newTable(opts ...Option) *table { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // sendEvent sends events to all subscribed watchers | ||||||
|  | func (t *table) sendEvent(e *Event) { | ||||||
|  | 	t.RLock() | ||||||
|  | 	defer t.RUnlock() | ||||||
|  |  | ||||||
|  | 	for _, w := range t.watchers { | ||||||
|  | 		select { | ||||||
|  | 		case w.resChan <- e: | ||||||
|  | 		case <-w.done: | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // Create creates new route in the routing table | // Create creates new route in the routing table | ||||||
| func (t *table) Create(r Route) error { | func (t *table) Create(r Route) error { | ||||||
| 	service := r.Service | 	service := r.Service | ||||||
| @@ -63,8 +83,10 @@ func (t *table) Delete(r Route) error { | |||||||
| 		return ErrRouteNotFound | 		return ErrRouteNotFound | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	delete(t.routes[service], sum) | 	if _, ok := t.routes[service][sum]; ok { | ||||||
| 	go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r}) | 		delete(t.routes[service], sum) | ||||||
|  | 		go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -85,8 +107,10 @@ func (t *table) Update(r Route) error { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t.routes[service][sum] = r | 	if _, ok := t.routes[service][sum]; !ok { | ||||||
| 	go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r}) | 		t.routes[service][sum] = r | ||||||
|  | 		go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -106,21 +130,23 @@ func (t *table) List() ([]Route, error) { | |||||||
| 	return routes, nil | 	return routes, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // isMatch checks if the route matches given network and router | // isMatch checks if the route matches given query options | ||||||
| func isMatch(route Route, network, router string) bool { | func isMatch(route Route, gateway, network, router string) bool { | ||||||
| 	if network == "*" || network == route.Network { | 	if gateway == "*" || gateway == route.Gateway { | ||||||
| 		if router == "*" || router == route.Gateway { | 		if network == "*" || network == route.Network { | ||||||
| 			return true | 			if router == "*" || router == route.Router { | ||||||
|  | 				return true | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| // findRoutes finds all the routes for given network and router and returns them | // findRoutes finds all the routes for given network and router and returns them | ||||||
| func findRoutes(routes map[uint64]Route, network, router string) []Route { | func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route { | ||||||
| 	var results []Route | 	var results []Route | ||||||
| 	for _, route := range routes { | 	for _, route := range routes { | ||||||
| 		if isMatch(route, network, router) { | 		if isMatch(route, gateway, network, router) { | ||||||
| 			results = append(results, route) | 			results = append(results, route) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -136,13 +162,13 @@ func (t *table) Query(q Query) ([]Route, error) { | |||||||
| 		if _, ok := t.routes[q.Options().Service]; !ok { | 		if _, ok := t.routes[q.Options().Service]; !ok { | ||||||
| 			return nil, ErrRouteNotFound | 			return nil, ErrRouteNotFound | ||||||
| 		} | 		} | ||||||
| 		return findRoutes(t.routes[q.Options().Service], q.Options().Network, q.Options().Gateway), nil | 		return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var results []Route | 	var results []Route | ||||||
| 	// search through all destinations | 	// search through all destinations | ||||||
| 	for _, routes := range t.routes { | 	for _, routes := range t.routes { | ||||||
| 		results = append(results, findRoutes(routes, q.Options().Network, q.Options().Gateway)...) | 		results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return results, nil | 	return results, nil | ||||||
| @@ -181,23 +207,3 @@ func (t *table) Watch(opts ...WatchOption) (Watcher, error) { | |||||||
|  |  | ||||||
| 	return w, nil | 	return w, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // sendEvent sends events to all subscribed watchers |  | ||||||
| func (t *table) sendEvent(e *Event) { |  | ||||||
| 	t.RLock() |  | ||||||
| 	defer t.RUnlock() |  | ||||||
|  |  | ||||||
| 	for _, w := range t.watchers { |  | ||||||
| 		select { |  | ||||||
| 		case w.resChan <- e: |  | ||||||
| 		case <-w.done: |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrRouteNotFound is returned when no route was found in the routing table |  | ||||||
| 	ErrRouteNotFound = errors.New("route not found") |  | ||||||
| 	// ErrDuplicateRoute is returned when the route already exists |  | ||||||
| 	ErrDuplicateRoute = errors.New("duplicate route") |  | ||||||
| ) |  | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ func testSetup() (*table, Route) { | |||||||
| 		Service: "dest.svc", | 		Service: "dest.svc", | ||||||
| 		Gateway: "dest.gw", | 		Gateway: "dest.gw", | ||||||
| 		Network: "dest.network", | 		Network: "dest.network", | ||||||
|  | 		Router:  "src.router", | ||||||
| 		Link:    "det.link", | 		Link:    "det.link", | ||||||
| 		Metric:  10, | 		Metric:  10, | ||||||
| 	} | 	} | ||||||
| @@ -109,11 +110,13 @@ func TestQuery(t *testing.T) { | |||||||
| 	svc := []string{"svc1", "svc2", "svc3"} | 	svc := []string{"svc1", "svc2", "svc3"} | ||||||
| 	net := []string{"net1", "net2", "net1"} | 	net := []string{"net1", "net2", "net1"} | ||||||
| 	gw := []string{"gw1", "gw2", "gw3"} | 	gw := []string{"gw1", "gw2", "gw3"} | ||||||
|  | 	rtr := []string{"rtr1", "rt2", "rt3"} | ||||||
|  |  | ||||||
| 	for i := 0; i < len(svc); i++ { | 	for i := 0; i < len(svc); i++ { | ||||||
| 		route.Service = svc[i] | 		route.Service = svc[i] | ||||||
| 		route.Network = net[i] | 		route.Network = net[i] | ||||||
| 		route.Gateway = gw[i] | 		route.Gateway = gw[i] | ||||||
|  | 		route.Router = rtr[i] | ||||||
| 		if err := table.Create(route); err != nil { | 		if err := table.Create(route); err != nil { | ||||||
| 			t.Errorf("error adding route: %s", err) | 			t.Errorf("error adding route: %s", err) | ||||||
| 		} | 		} | ||||||
| @@ -127,8 +130,9 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("error looking up routes: %s", err) | 		t.Errorf("error looking up routes: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular net | 	// query routes particular network | ||||||
| 	query = NewQuery(QueryNetwork("net1")) | 	network := "net1" | ||||||
|  | 	query = NewQuery(QueryNetwork(network)) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -139,7 +143,13 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 2, len(routes)) | 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 2, len(routes)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular gateway | 	for _, route := range routes { | ||||||
|  | 		if route.Network != network { | ||||||
|  | 			t.Errorf("incorrect route returned. Expected network: %s, found: %s", network, route.Network) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// query routes for particular gateway | ||||||
| 	gateway := "gw1" | 	gateway := "gw1" | ||||||
| 	query = NewQuery(QueryGateway(gateway)) | 	query = NewQuery(QueryGateway(gateway)) | ||||||
|  |  | ||||||
| @@ -156,11 +166,28 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect route returned. Expected gateway: %s, found: %s", gateway, routes[0].Gateway) | 		t.Errorf("incorrect route returned. Expected gateway: %s, found: %s", gateway, routes[0].Gateway) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular route | 	// query routes for particular router | ||||||
| 	network := "net1" | 	router := "rtr1" | ||||||
|  | 	query = NewQuery(QueryRouter(router)) | ||||||
|  |  | ||||||
|  | 	routes, err = table.Query(query) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("error looking up routes: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(routes) != 1 { | ||||||
|  | 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 1, len(routes)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if routes[0].Router != router { | ||||||
|  | 		t.Errorf("incorrect route returned. Expected router: %s, found: %s", router, routes[0].Router) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// query particular gateway and network | ||||||
| 	query = NewQuery( | 	query = NewQuery( | ||||||
| 		QueryGateway(gateway), | 		QueryGateway(gateway), | ||||||
| 		QueryNetwork(network), | 		QueryNetwork(network), | ||||||
|  | 		QueryRouter(router), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
| @@ -180,7 +207,11 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect network returned. Expected network: %s, found: %s", network, routes[0].Network) | 		t.Errorf("incorrect network returned. Expected network: %s, found: %s", network, routes[0].Network) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// bullshit route query | 	if routes[0].Router != router { | ||||||
|  | 		t.Errorf("incorrect route returned. Expected router: %s, found: %s", router, routes[0].Router) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// non-existen route query | ||||||
| 	query = NewQuery(QueryService("foobar")) | 	query = NewQuery(QueryService("foobar")) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
|   | |||||||
| @@ -6,6 +6,11 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// ErrWatcherStopped is returned when routing table watcher has been stopped | ||||||
|  | 	ErrWatcherStopped = errors.New("watcher stopped") | ||||||
|  | ) | ||||||
|  |  | ||||||
| // EventType defines routing table event | // EventType defines routing table event | ||||||
| type EventType int | type EventType int | ||||||
|  |  | ||||||
| @@ -42,9 +47,6 @@ type Event struct { | |||||||
| 	Route Route | 	Route Route | ||||||
| } | } | ||||||
|  |  | ||||||
| // WatchOption is used to define what routes to watch in the table |  | ||||||
| type WatchOption func(*WatchOptions) |  | ||||||
|  |  | ||||||
| // Watcher defines routing table watcher interface | // Watcher defines routing table watcher interface | ||||||
| // Watcher returns updates to the routing table | // Watcher returns updates to the routing table | ||||||
| type Watcher interface { | type Watcher interface { | ||||||
| @@ -56,7 +58,11 @@ type Watcher interface { | |||||||
| 	Stop() | 	Stop() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // WatchOption is used to define what routes to watch in the table | ||||||
|  | type WatchOption func(*WatchOptions) | ||||||
|  |  | ||||||
| // WatchOptions are table watcher options | // WatchOptions are table watcher options | ||||||
|  | // TODO: expand the options to watch based on other criteria | ||||||
| type WatchOptions struct { | type WatchOptions struct { | ||||||
| 	// Service allows to watch specific service routes | 	// Service allows to watch specific service routes | ||||||
| 	Service string | 	Service string | ||||||
| @@ -70,6 +76,7 @@ func WatchService(s string) WatchOption { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // tableWatcher implements routing table Watcher | ||||||
| type tableWatcher struct { | type tableWatcher struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	id      string | 	id      string | ||||||
| @@ -113,8 +120,3 @@ func (w *tableWatcher) Stop() { | |||||||
| 		close(w.done) | 		close(w.done) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrWatcherStopped is returned when routing table watcher has been stopped |  | ||||||
| 	ErrWatcherStopped = errors.New("watcher stopped") |  | ||||||
| ) |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								service.go
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								service.go
									
									
									
									
									
								
							| @@ -3,6 +3,7 @@ package micro | |||||||
| import ( | import ( | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/signal" | 	"os/signal" | ||||||
|  | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"syscall" | 	"syscall" | ||||||
|  |  | ||||||
| @@ -10,7 +11,9 @@ import ( | |||||||
| 	"github.com/micro/go-micro/config/cmd" | 	"github.com/micro/go-micro/config/cmd" | ||||||
| 	"github.com/micro/go-micro/debug/handler" | 	"github.com/micro/go-micro/debug/handler" | ||||||
| 	"github.com/micro/go-micro/metadata" | 	"github.com/micro/go-micro/metadata" | ||||||
|  | 	"github.com/micro/go-micro/plugin" | ||||||
| 	"github.com/micro/go-micro/server" | 	"github.com/micro/go-micro/server" | ||||||
|  | 	"github.com/micro/go-micro/util/log" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type service struct { | type service struct { | ||||||
| @@ -44,6 +47,24 @@ func (s *service) Init(opts ...Option) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	s.once.Do(func() { | 	s.once.Do(func() { | ||||||
|  | 		// setup the plugins | ||||||
|  | 		for _, p := range strings.Split(os.Getenv("MICRO_PLUGIN"), ",") { | ||||||
|  | 			if len(p) == 0 { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// load the plugin | ||||||
|  | 			c, err := plugin.Load(p) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Fatal(err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// initialise the plugin | ||||||
|  | 			if err := plugin.Init(c); err != nil { | ||||||
|  | 				log.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		// Initialise the command flags, overriding new service | 		// Initialise the command flags, overriding new service | ||||||
| 		_ = s.opts.Cmd.Init( | 		_ = s.opts.Cmd.Init( | ||||||
| 			cmd.Broker(&s.opts.Broker), | 			cmd.Broker(&s.opts.Broker), | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ func (t *tunBroker) Disconnect() error { | |||||||
| func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.PublishOption) error { | func (t *tunBroker) Publish(topic string, m *broker.Message, opts ...broker.PublishOption) error { | ||||||
| 	// TODO: this is probably inefficient, we might want to just maintain an open connection | 	// TODO: this is probably inefficient, we might want to just maintain an open connection | ||||||
| 	// it may be easier to add broadcast to the tunnel | 	// it may be easier to add broadcast to the tunnel | ||||||
| 	c, err := t.tunnel.Dial(topic) | 	c, err := t.tunnel.Dial(topic, tunnel.DialMulticast()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										101
									
								
								tunnel/link.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								tunnel/link.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | package tunnel | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/google/uuid" | ||||||
|  | 	"github.com/micro/go-micro/transport" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type link struct { | ||||||
|  | 	transport.Socket | ||||||
|  |  | ||||||
|  | 	sync.RWMutex | ||||||
|  |  | ||||||
|  | 	// unique id of this link e.g uuid | ||||||
|  | 	// which we define for ourselves | ||||||
|  | 	id string | ||||||
|  | 	// whether its a loopback connection | ||||||
|  | 	// this flag is used by the transport listener | ||||||
|  | 	// which accepts inbound quic connections | ||||||
|  | 	loopback bool | ||||||
|  | 	// whether its actually connected | ||||||
|  | 	// dialled side sets it to connected | ||||||
|  | 	// after sending the message. the | ||||||
|  | 	// listener waits for the connect | ||||||
|  | 	connected bool | ||||||
|  | 	// the last time we received a keepalive | ||||||
|  | 	// on this link from the remote side | ||||||
|  | 	lastKeepAlive time.Time | ||||||
|  | 	// channels keeps a mapping of channels and last seen | ||||||
|  | 	channels map[string]time.Time | ||||||
|  | 	// stop the link | ||||||
|  | 	closed chan bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newLink(s transport.Socket) *link { | ||||||
|  | 	l := &link{ | ||||||
|  | 		Socket:   s, | ||||||
|  | 		id:       uuid.New().String(), | ||||||
|  | 		channels: make(map[string]time.Time), | ||||||
|  | 		closed:   make(chan bool), | ||||||
|  | 	} | ||||||
|  | 	go l.run() | ||||||
|  | 	return l | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *link) run() { | ||||||
|  | 	t := time.NewTicker(time.Minute) | ||||||
|  | 	defer t.Stop() | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case <-l.closed: | ||||||
|  | 			return | ||||||
|  | 		case <-t.C: | ||||||
|  | 			// drop any channel mappings older than 2 minutes | ||||||
|  | 			var kill []string | ||||||
|  | 			killTime := time.Minute * 2 | ||||||
|  |  | ||||||
|  | 			l.RLock() | ||||||
|  | 			for ch, t := range l.channels { | ||||||
|  | 				if d := time.Since(t); d > killTime { | ||||||
|  | 					kill = append(kill, ch) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			l.RUnlock() | ||||||
|  |  | ||||||
|  | 			// if nothing to kill don't bother with a wasted lock | ||||||
|  | 			if len(kill) == 0 { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// kill the channels! | ||||||
|  | 			l.Lock() | ||||||
|  | 			for _, ch := range kill { | ||||||
|  | 				delete(l.channels, ch) | ||||||
|  | 			} | ||||||
|  | 			l.Unlock() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *link) Id() string { | ||||||
|  | 	l.RLock() | ||||||
|  | 	defer l.RUnlock() | ||||||
|  |  | ||||||
|  | 	return l.id | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *link) Close() error { | ||||||
|  | 	select { | ||||||
|  | 	case <-l.closed: | ||||||
|  | 		return nil | ||||||
|  | 	default: | ||||||
|  | 		close(l.closed) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @@ -8,8 +8,13 @@ import ( | |||||||
| 	"github.com/micro/go-micro/transport" | 	"github.com/micro/go-micro/transport" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | var ( | ||||||
|  | 	// ErrLinkClosed is returned when attempting i/o operation on the closed link | ||||||
|  | 	ErrLinkClosed = errors.New("link closed") | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| // Link is a layer on top of a transport socket with the | // Link is a layer on top of a transport socket with the | ||||||
| // buffering send and recv queue's with the ability to | // buffering send and recv queues with the ability to | ||||||
| // measure the actual transport link and reconnect if | // measure the actual transport link and reconnect if | ||||||
| // an address is specified. | // an address is specified. | ||||||
| type Link interface { | type Link interface { | ||||||
| @@ -28,10 +33,6 @@ type Link interface { | |||||||
| 	Length() int | 	Length() int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var ( |  | ||||||
| 	ErrLinkClosed = errors.New("link closed") |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // NewLink creates a new link on top of a socket | // NewLink creates a new link on top of a socket | ||||||
| func NewLink(opts ...options.Option) Link { | func NewLink(opts ...options.Option) Link { | ||||||
| 	return newLink(options.NewOptions(opts...)) | 	return newLink(options.NewOptions(opts...)) | ||||||
| @@ -2,79 +2,148 @@ package tunnel | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/util/log" | 	"github.com/micro/go-micro/util/log" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type tunListener struct { | type tunListener struct { | ||||||
| 	// address of the listener | 	// address of the listener | ||||||
| 	addr string | 	channel string | ||||||
| 	// the accept channel | 	// the accept channel | ||||||
| 	accept chan *socket | 	accept chan *session | ||||||
| 	// the channel to close | 	// the channel to close | ||||||
| 	closed chan bool | 	closed chan bool | ||||||
| 	// the tunnel closed channel | 	// the tunnel closed channel | ||||||
| 	tunClosed chan bool | 	tunClosed chan bool | ||||||
| 	// the connection | 	// the listener session | ||||||
| 	conn Conn | 	session *session | ||||||
| 	// the listener socket | 	// del func to kill listener | ||||||
| 	socket *socket | 	delFunc func() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // periodically announce self | ||||||
|  | func (t *tunListener) announce() { | ||||||
|  | 	tick := time.NewTicker(time.Second * 30) | ||||||
|  | 	defer tick.Stop() | ||||||
|  |  | ||||||
|  | 	// first announcement | ||||||
|  | 	t.session.Announce() | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case <-tick.C: | ||||||
|  | 			t.session.Announce() | ||||||
|  | 		case <-t.closed: | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *tunListener) process() { | func (t *tunListener) process() { | ||||||
| 	// our connection map for session | 	// our connection map for session | ||||||
| 	conns := make(map[string]*socket) | 	conns := make(map[string]*session) | ||||||
|  |  | ||||||
|  | 	defer func() { | ||||||
|  | 		// close the sessions | ||||||
|  | 		for _, conn := range conns { | ||||||
|  | 			conn.Close() | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
| 		select { | 		select { | ||||||
| 		case <-t.closed: | 		case <-t.closed: | ||||||
| 			return | 			return | ||||||
|  | 		case <-t.tunClosed: | ||||||
|  | 			t.Close() | ||||||
|  | 			return | ||||||
| 		// receive a new message | 		// receive a new message | ||||||
| 		case m := <-t.socket.recv: | 		case m := <-t.session.recv: | ||||||
| 			// get a socket | 			// get a session | ||||||
| 			sock, ok := conns[m.session] | 			sess, ok := conns[m.session] | ||||||
| 			log.Debugf("Tunnel listener received id %s session %s exists: %t", m.id, m.session, ok) | 			log.Debugf("Tunnel listener received channel %s session %s exists: %t", m.channel, m.session, ok) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				// create a new socket session | 				switch m.typ { | ||||||
| 				sock = &socket{ | 				case "open", "session": | ||||||
| 					// our tunnel id | 				default: | ||||||
| 					id: m.id, | 					continue | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// create a new session session | ||||||
|  | 				sess = &session{ | ||||||
|  | 					// the id of the remote side | ||||||
|  | 					tunnel: m.tunnel, | ||||||
|  | 					// the channel | ||||||
|  | 					channel: m.channel, | ||||||
| 					// the session id | 					// the session id | ||||||
| 					session: m.session, | 					session: m.session, | ||||||
|  | 					// is loopback conn | ||||||
|  | 					loopback: m.loopback, | ||||||
|  | 					// the link the message was received on | ||||||
|  | 					link: m.link, | ||||||
|  | 					// set multicast | ||||||
|  | 					multicast: m.multicast, | ||||||
| 					// close chan | 					// close chan | ||||||
| 					closed: make(chan bool), | 					closed: make(chan bool), | ||||||
| 					// recv called by the acceptor | 					// recv called by the acceptor | ||||||
| 					recv: make(chan *message, 128), | 					recv: make(chan *message, 128), | ||||||
| 					// use the internal send buffer | 					// use the internal send buffer | ||||||
| 					send: t.socket.send, | 					send: t.session.send, | ||||||
| 					// wait | 					// wait | ||||||
| 					wait: make(chan bool), | 					wait: make(chan bool), | ||||||
|  | 					// error channel | ||||||
|  | 					errChan: make(chan error, 1), | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				// save the socket | 				// save the session | ||||||
| 				conns[m.session] = sock | 				conns[m.session] = sess | ||||||
|  |  | ||||||
| 				// send to accept chan |  | ||||||
| 				select { | 				select { | ||||||
| 				case <-t.closed: | 				case <-t.closed: | ||||||
| 					return | 					return | ||||||
| 				case t.accept <- sock: | 				// send to accept chan | ||||||
|  | 				case t.accept <- sess: | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// an existing session was found | ||||||
|  |  | ||||||
|  | 			// received a close message | ||||||
|  | 			switch m.typ { | ||||||
|  | 			case "close": | ||||||
|  | 				select { | ||||||
|  | 				case <-sess.closed: | ||||||
|  | 					// no op | ||||||
|  | 					delete(conns, m.session) | ||||||
|  | 				default: | ||||||
|  | 					// close and delete session | ||||||
|  | 					close(sess.closed) | ||||||
|  | 					delete(conns, m.session) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// continue | ||||||
|  | 				continue | ||||||
|  | 			case "session": | ||||||
|  | 				// operate on this | ||||||
|  | 			default: | ||||||
|  | 				// non operational type | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			// send this to the accept chan | 			// send this to the accept chan | ||||||
| 			select { | 			select { | ||||||
| 			case <-sock.closed: | 			case <-sess.closed: | ||||||
| 				delete(conns, m.session) | 				delete(conns, m.session) | ||||||
| 			case sock.recv <- m: | 			case sess.recv <- m: | ||||||
| 				log.Debugf("Tunnel listener sent to recv chan id %s session %s", m.id, m.session) | 				log.Debugf("Tunnel listener sent to recv chan channel %s session %s", m.channel, m.session) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *tunListener) Addr() string { | func (t *tunListener) Channel() string { | ||||||
| 	return t.addr | 	return t.channel | ||||||
| } | } | ||||||
|  |  | ||||||
| // Close closes tunnel listener | // Close closes tunnel listener | ||||||
| @@ -83,26 +152,33 @@ func (t *tunListener) Close() error { | |||||||
| 	case <-t.closed: | 	case <-t.closed: | ||||||
| 		return nil | 		return nil | ||||||
| 	default: | 	default: | ||||||
|  | 		// close and delete | ||||||
|  | 		t.delFunc() | ||||||
|  | 		t.session.Close() | ||||||
| 		close(t.closed) | 		close(t.closed) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Everytime accept is called we essentially block till we get a new connection | // Everytime accept is called we essentially block till we get a new connection | ||||||
| func (t *tunListener) Accept() (Conn, error) { | func (t *tunListener) Accept() (Session, error) { | ||||||
| 	select { | 	select { | ||||||
| 	// if the socket is closed return | 	// if the session is closed return | ||||||
| 	case <-t.closed: | 	case <-t.closed: | ||||||
| 		return nil, io.EOF | 		return nil, io.EOF | ||||||
| 	case <-t.tunClosed: | 	case <-t.tunClosed: | ||||||
| 		// close the listener when the tunnel closes | 		// close the listener when the tunnel closes | ||||||
| 		t.Close() |  | ||||||
| 		return nil, io.EOF | 		return nil, io.EOF | ||||||
| 	// wait for a new connection | 	// wait for a new connection | ||||||
| 	case c, ok := <-t.accept: | 	case c, ok := <-t.accept: | ||||||
|  | 		// check if the accept chan is closed | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, io.EOF | 			return nil, io.EOF | ||||||
| 		} | 		} | ||||||
|  | 		// send back the accept | ||||||
|  | 		if err := c.Accept(); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
| 		return c, nil | 		return c, nil | ||||||
| 	} | 	} | ||||||
| 	return nil, nil | 	return nil, nil | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| package tunnel | package tunnel | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| 	"github.com/micro/go-micro/transport" | 	"github.com/micro/go-micro/transport" | ||||||
| 	"github.com/micro/go-micro/transport/quic" | 	"github.com/micro/go-micro/transport/quic" | ||||||
| @@ -9,6 +11,8 @@ import ( | |||||||
| var ( | var ( | ||||||
| 	// DefaultAddress is default tunnel bind address | 	// DefaultAddress is default tunnel bind address | ||||||
| 	DefaultAddress = ":0" | 	DefaultAddress = ":0" | ||||||
|  | 	// The shared default token | ||||||
|  | 	DefaultToken = "micro" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type Option func(*Options) | type Option func(*Options) | ||||||
| @@ -21,10 +25,21 @@ type Options struct { | |||||||
| 	Address string | 	Address string | ||||||
| 	// Nodes are remote nodes | 	// Nodes are remote nodes | ||||||
| 	Nodes []string | 	Nodes []string | ||||||
|  | 	// The shared auth token | ||||||
|  | 	Token string | ||||||
| 	// Transport listens to incoming connections | 	// Transport listens to incoming connections | ||||||
| 	Transport transport.Transport | 	Transport transport.Transport | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type DialOption func(*DialOptions) | ||||||
|  |  | ||||||
|  | type DialOptions struct { | ||||||
|  | 	// specify a multicast connection | ||||||
|  | 	Multicast bool | ||||||
|  | 	// the dial timeout | ||||||
|  | 	Timeout time.Duration | ||||||
|  | } | ||||||
|  |  | ||||||
| // The tunnel id | // The tunnel id | ||||||
| func Id(id string) Option { | func Id(id string) Option { | ||||||
| 	return func(o *Options) { | 	return func(o *Options) { | ||||||
| @@ -46,6 +61,13 @@ func Nodes(n ...string) Option { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Token sets the shared token for auth | ||||||
|  | func Token(t string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Token = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // Transport listens for incoming connections | // Transport listens for incoming connections | ||||||
| func Transport(t transport.Transport) Option { | func Transport(t transport.Transport) Option { | ||||||
| 	return func(o *Options) { | 	return func(o *Options) { | ||||||
| @@ -58,6 +80,22 @@ func DefaultOptions() Options { | |||||||
| 	return Options{ | 	return Options{ | ||||||
| 		Id:        uuid.New().String(), | 		Id:        uuid.New().String(), | ||||||
| 		Address:   DefaultAddress, | 		Address:   DefaultAddress, | ||||||
|  | 		Token:     DefaultToken, | ||||||
| 		Transport: quic.NewTransport(), | 		Transport: quic.NewTransport(), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Dial options | ||||||
|  |  | ||||||
|  | // Dial multicast sets the multicast option to send only to those mapped | ||||||
|  | func DialMulticast() DialOption { | ||||||
|  | 	return func(o *DialOptions) { | ||||||
|  | 		o.Multicast = true | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func DialTimeout(t time.Duration) DialOption { | ||||||
|  | 	return func(o *DialOptions) { | ||||||
|  | 		o.Timeout = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										286
									
								
								tunnel/session.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								tunnel/session.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | |||||||
|  | package tunnel | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"io" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/transport" | ||||||
|  | 	"github.com/micro/go-micro/util/log" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // session is our pseudo session for transport.Socket | ||||||
|  | type session struct { | ||||||
|  | 	// the tunnel id | ||||||
|  | 	tunnel string | ||||||
|  | 	// the channel name | ||||||
|  | 	channel string | ||||||
|  | 	// the session id based on Micro.Tunnel-Session | ||||||
|  | 	session string | ||||||
|  | 	// closed | ||||||
|  | 	closed chan bool | ||||||
|  | 	// remote addr | ||||||
|  | 	remote string | ||||||
|  | 	// local addr | ||||||
|  | 	local string | ||||||
|  | 	// send chan | ||||||
|  | 	send chan *message | ||||||
|  | 	// recv chan | ||||||
|  | 	recv chan *message | ||||||
|  | 	// wait until we have a connection | ||||||
|  | 	wait chan bool | ||||||
|  | 	// if the discovery worked | ||||||
|  | 	discovered bool | ||||||
|  | 	// if the session was accepted | ||||||
|  | 	accepted bool | ||||||
|  | 	// outbound marks the session as outbound dialled connection | ||||||
|  | 	outbound bool | ||||||
|  | 	// lookback marks the session as a loopback on the inbound | ||||||
|  | 	loopback bool | ||||||
|  | 	// if the session is multicast | ||||||
|  | 	multicast bool | ||||||
|  | 	// if the session is broadcast | ||||||
|  | 	broadcast bool | ||||||
|  | 	// the timeout | ||||||
|  | 	timeout time.Duration | ||||||
|  | 	// the link on which this message was received | ||||||
|  | 	link string | ||||||
|  | 	// the error response | ||||||
|  | 	errChan chan error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // message is sent over the send channel | ||||||
|  | type message struct { | ||||||
|  | 	// type of message | ||||||
|  | 	typ string | ||||||
|  | 	// tunnel id | ||||||
|  | 	tunnel string | ||||||
|  | 	// channel name | ||||||
|  | 	channel string | ||||||
|  | 	// the session id | ||||||
|  | 	session string | ||||||
|  | 	// outbound marks the message as outbound | ||||||
|  | 	outbound bool | ||||||
|  | 	// loopback marks the message intended for loopback | ||||||
|  | 	loopback bool | ||||||
|  | 	// whether to send as multicast | ||||||
|  | 	multicast bool | ||||||
|  | 	// broadcast sets the broadcast type | ||||||
|  | 	broadcast bool | ||||||
|  | 	// the link to send the message on | ||||||
|  | 	link string | ||||||
|  | 	// transport data | ||||||
|  | 	data *transport.Message | ||||||
|  | 	// the error channel | ||||||
|  | 	errChan chan error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *session) Remote() string { | ||||||
|  | 	return s.remote | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *session) Local() string { | ||||||
|  | 	return s.local | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *session) Id() string { | ||||||
|  | 	return s.session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *session) Channel() string { | ||||||
|  | 	return s.channel | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newMessage creates a new message based on the session | ||||||
|  | func (s *session) newMessage(typ string) *message { | ||||||
|  | 	return &message{ | ||||||
|  | 		typ:       typ, | ||||||
|  | 		tunnel:    s.tunnel, | ||||||
|  | 		channel:   s.channel, | ||||||
|  | 		session:   s.session, | ||||||
|  | 		outbound:  s.outbound, | ||||||
|  | 		loopback:  s.loopback, | ||||||
|  | 		multicast: s.multicast, | ||||||
|  | 		link:      s.link, | ||||||
|  | 		errChan:   s.errChan, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Open will fire the open message for the session. This is called by the dialler. | ||||||
|  | func (s *session) Open() error { | ||||||
|  | 	// create a new message | ||||||
|  | 	msg := s.newMessage("open") | ||||||
|  |  | ||||||
|  | 	// send open message | ||||||
|  | 	s.send <- msg | ||||||
|  |  | ||||||
|  | 	// wait for an error response for send | ||||||
|  | 	select { | ||||||
|  | 	case err := <-msg.errChan: | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// we don't wait on multicast | ||||||
|  | 	if s.multicast { | ||||||
|  | 		s.accepted = true | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// now wait for the accept | ||||||
|  | 	select { | ||||||
|  | 	case msg = <-s.recv: | ||||||
|  | 		if msg.typ != "accept" { | ||||||
|  | 			log.Debugf("Received non accept message in Open %s", msg.typ) | ||||||
|  | 			return errors.New("failed to connect") | ||||||
|  | 		} | ||||||
|  | 		// set to accepted | ||||||
|  | 		s.accepted = true | ||||||
|  | 		// set link | ||||||
|  | 		s.link = msg.link | ||||||
|  | 	case <-time.After(s.timeout): | ||||||
|  | 		return ErrDialTimeout | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Accept sends the accept response to an open message from a dialled connection | ||||||
|  | func (s *session) Accept() error { | ||||||
|  | 	msg := s.newMessage("accept") | ||||||
|  |  | ||||||
|  | 	// send the accept message | ||||||
|  | 	select { | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	case s.send <- msg: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// wait for send response | ||||||
|  | 	select { | ||||||
|  | 	case err := <-s.errChan: | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Announce sends an announcement to notify that this session exists. This is primarily used by the listener. | ||||||
|  | func (s *session) Announce() error { | ||||||
|  | 	msg := s.newMessage("announce") | ||||||
|  | 	// we don't need an error back | ||||||
|  | 	msg.errChan = nil | ||||||
|  | 	// announce to all | ||||||
|  | 	msg.broadcast = true | ||||||
|  | 	// we don't need the link | ||||||
|  | 	msg.link = "" | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case s.send <- msg: | ||||||
|  | 		return nil | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Send is used to send a message | ||||||
|  | func (s *session) Send(m *transport.Message) error { | ||||||
|  | 	select { | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	default: | ||||||
|  | 		// no op | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// make copy | ||||||
|  | 	data := &transport.Message{ | ||||||
|  | 		Header: make(map[string]string), | ||||||
|  | 		Body:   m.Body, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for k, v := range m.Header { | ||||||
|  | 		data.Header[k] = v | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// create a new message | ||||||
|  | 	msg := s.newMessage("session") | ||||||
|  | 	// set the data | ||||||
|  | 	msg.data = data | ||||||
|  |  | ||||||
|  | 	// if multicast don't set the link | ||||||
|  | 	if s.multicast { | ||||||
|  | 		msg.link = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Debugf("Appending %+v to send backlog", msg) | ||||||
|  | 	// send the actual message | ||||||
|  | 	s.send <- msg | ||||||
|  |  | ||||||
|  | 	// wait for an error response | ||||||
|  | 	select { | ||||||
|  | 	case err := <-msg.errChan: | ||||||
|  | 		return err | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return io.EOF | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Recv is used to receive a message | ||||||
|  | func (s *session) Recv(m *transport.Message) error { | ||||||
|  | 	select { | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		return errors.New("session is closed") | ||||||
|  | 	default: | ||||||
|  | 		// no op | ||||||
|  | 	} | ||||||
|  | 	// recv from backlog | ||||||
|  | 	msg := <-s.recv | ||||||
|  |  | ||||||
|  | 	// check the error if one exists | ||||||
|  | 	select { | ||||||
|  | 	case err := <-msg.errChan: | ||||||
|  | 		return err | ||||||
|  | 	default: | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Debugf("Received %+v from recv backlog", msg) | ||||||
|  | 	// set message | ||||||
|  | 	*m = *msg.data | ||||||
|  | 	// return nil | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Close closes the session by sending a close message | ||||||
|  | func (s *session) Close() error { | ||||||
|  | 	select { | ||||||
|  | 	case <-s.closed: | ||||||
|  | 		// no op | ||||||
|  | 	default: | ||||||
|  | 		close(s.closed) | ||||||
|  |  | ||||||
|  | 		// append to backlog | ||||||
|  | 		msg := s.newMessage("close") | ||||||
|  | 		// no error response on close | ||||||
|  | 		msg.errChan = nil | ||||||
|  |  | ||||||
|  | 		// send the close message | ||||||
|  | 		select { | ||||||
|  | 		case s.send <- msg: | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										115
									
								
								tunnel/socket.go
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								tunnel/socket.go
									
									
									
									
									
								
							| @@ -1,115 +0,0 @@ | |||||||
| package tunnel |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/transport" |  | ||||||
| 	"github.com/micro/go-micro/util/log" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // socket is our pseudo socket for transport.Socket |  | ||||||
| type socket struct { |  | ||||||
| 	// socket id based on Micro-Tunnel |  | ||||||
| 	id string |  | ||||||
| 	// the session id based on Micro.Tunnel-Session |  | ||||||
| 	session string |  | ||||||
| 	// closed |  | ||||||
| 	closed chan bool |  | ||||||
| 	// remote addr |  | ||||||
| 	remote string |  | ||||||
| 	// local addr |  | ||||||
| 	local string |  | ||||||
| 	// send chan |  | ||||||
| 	send chan *message |  | ||||||
| 	// recv chan |  | ||||||
| 	recv chan *message |  | ||||||
| 	// wait until we have a connection |  | ||||||
| 	wait chan bool |  | ||||||
| 	// outbound marks the socket as outbound |  | ||||||
| 	outbound bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // message is sent over the send channel |  | ||||||
| type message struct { |  | ||||||
| 	// tunnel id |  | ||||||
| 	id string |  | ||||||
| 	// the session id |  | ||||||
| 	session string |  | ||||||
| 	// outbound marks the message as outbound |  | ||||||
| 	outbound bool |  | ||||||
| 	// transport data |  | ||||||
| 	data *transport.Message |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Remote() string { |  | ||||||
| 	return s.remote |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Local() string { |  | ||||||
| 	return s.local |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Id() string { |  | ||||||
| 	return s.id |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Session() string { |  | ||||||
| 	return s.session |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Send(m *transport.Message) error { |  | ||||||
| 	select { |  | ||||||
| 	case <-s.closed: |  | ||||||
| 		return errors.New("socket is closed") |  | ||||||
| 	default: |  | ||||||
| 		// no op |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// make copy |  | ||||||
| 	data := &transport.Message{ |  | ||||||
| 		Header: make(map[string]string), |  | ||||||
| 		Body:   m.Body, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for k, v := range m.Header { |  | ||||||
| 		data.Header[k] = v |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// append to backlog |  | ||||||
| 	msg := &message{ |  | ||||||
| 		id:       s.id, |  | ||||||
| 		session:  s.session, |  | ||||||
| 		outbound: s.outbound, |  | ||||||
| 		data:     data, |  | ||||||
| 	} |  | ||||||
| 	log.Debugf("Appending %+v to send backlog", msg) |  | ||||||
| 	s.send <- msg |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *socket) Recv(m *transport.Message) error { |  | ||||||
| 	select { |  | ||||||
| 	case <-s.closed: |  | ||||||
| 		return errors.New("socket is closed") |  | ||||||
| 	default: |  | ||||||
| 		// no op |  | ||||||
| 	} |  | ||||||
| 	// recv from backlog |  | ||||||
| 	msg := <-s.recv |  | ||||||
| 	log.Debugf("Received %+v from recv backlog", msg) |  | ||||||
| 	// set message |  | ||||||
| 	*m = *msg.data |  | ||||||
| 	// return nil |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Close closes the socket |  | ||||||
| func (s *socket) Close() error { |  | ||||||
| 	select { |  | ||||||
| 	case <-s.closed: |  | ||||||
| 		// no op |  | ||||||
| 	default: |  | ||||||
| 		close(s.closed) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @@ -10,7 +10,7 @@ type tunListener struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (t *tunListener) Addr() string { | func (t *tunListener) Addr() string { | ||||||
| 	return t.l.Addr() | 	return t.l.Channel() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *tunListener) Close() error { | func (t *tunListener) Close() error { | ||||||
|   | |||||||
| @@ -2,11 +2,23 @@ | |||||||
| package tunnel | package tunnel | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/transport" | 	"github.com/micro/go-micro/transport" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Tunnel creates a gre network tunnel on top of a link. | var ( | ||||||
| // It establishes multiple streams using the Micro-Tunnel-Id header | 	// DefaultDialTimeout is the dial timeout if none is specified | ||||||
|  | 	DefaultDialTimeout = time.Second * 5 | ||||||
|  | 	// ErrDialTimeout is returned by a call to Dial where the timeout occurs | ||||||
|  | 	ErrDialTimeout = errors.New("dial timeout") | ||||||
|  | 	// ErrDiscoverChan is returned when we failed to receive the "announce" back from a discovery | ||||||
|  | 	ErrDiscoverChan = errors.New("failed to discover channel") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Tunnel creates a gre tunnel on top of the go-micro/transport. | ||||||
|  | // It establishes multiple streams using the Micro-Tunnel-Channel header | ||||||
| // and Micro-Tunnel-Session header. The tunnel id is a hash of | // and Micro-Tunnel-Session header. The tunnel id is a hash of | ||||||
| // the address being requested. | // the address being requested. | ||||||
| type Tunnel interface { | type Tunnel interface { | ||||||
| @@ -17,27 +29,37 @@ type Tunnel interface { | |||||||
| 	Connect() error | 	Connect() error | ||||||
| 	// Close closes the tunnel | 	// Close closes the tunnel | ||||||
| 	Close() error | 	Close() error | ||||||
| 	// Dial an endpoint | 	// Connect to a channel | ||||||
| 	Dial(addr string) (Conn, error) | 	Dial(channel string, opts ...DialOption) (Session, error) | ||||||
| 	// Accept connections | 	// Accept connections on a channel | ||||||
| 	Listen(addr string) (Listener, error) | 	Listen(channel string) (Listener, error) | ||||||
|  | 	// All the links the tunnel is connected to | ||||||
|  | 	Links() []Link | ||||||
| 	// Name of the tunnel implementation | 	// Name of the tunnel implementation | ||||||
| 	String() string | 	String() string | ||||||
| } | } | ||||||
|  |  | ||||||
| // The listener provides similar constructs to the transport.Listener | // Link represents internal links to the tunnel | ||||||
| type Listener interface { | type Link interface { | ||||||
| 	Addr() string | 	// The id of the link | ||||||
| 	Close() error | 	Id() string | ||||||
| 	Accept() (Conn, error) | 	// honours transport socket | ||||||
|  | 	transport.Socket | ||||||
| } | } | ||||||
|  |  | ||||||
| // Conn is a connection dialed or accepted which includes the tunnel id and session | // The listener provides similar constructs to the transport.Listener | ||||||
| type Conn interface { | type Listener interface { | ||||||
| 	// Specifies the tunnel id | 	Accept() (Session, error) | ||||||
|  | 	Channel() string | ||||||
|  | 	Close() error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Session is a unique session created when dialling or accepting connections on the tunnel | ||||||
|  | type Session interface { | ||||||
|  | 	// The unique session id | ||||||
| 	Id() string | 	Id() string | ||||||
| 	// The session | 	// The channel name | ||||||
| 	Session() string | 	Channel() string | ||||||
| 	// a transport socket | 	// a transport socket | ||||||
| 	transport.Socket | 	transport.Socket | ||||||
| } | } | ||||||
|   | |||||||
| @@ -187,30 +187,15 @@ func testBrokenTunAccept(t *testing.T, tun Tunnel, wait chan bool, wg *sync.Wait | |||||||
| 	if err := c.Recv(m); err != nil { | 	if err := c.Recv(m); err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	tun.Close() |  | ||||||
|  |  | ||||||
| 	// re-start tunnel | 	// close all the links | ||||||
| 	err = tun.Connect() | 	for _, link := range tun.Links() { | ||||||
| 	if err != nil { | 		link.Close() | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	defer tun.Close() |  | ||||||
|  |  | ||||||
| 	// listen on some virtual address |  | ||||||
| 	tl, err = tun.Listen("test-tunnel") |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// receiver ready; notify sender | 	// receiver ready; notify sender | ||||||
| 	wait <- true | 	wait <- true | ||||||
|  |  | ||||||
| 	// accept a connection |  | ||||||
| 	c, err = tl.Accept() |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// accept the message | 	// accept the message | ||||||
| 	m = new(transport.Message) | 	m = new(transport.Message) | ||||||
| 	if err := c.Recv(m); err != nil { | 	if err := c.Recv(m); err != nil { | ||||||
| @@ -279,6 +264,7 @@ func TestReconnectTunnel(t *testing.T) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  | 	defer tunB.Close() | ||||||
|  |  | ||||||
| 	// we manually override the tunnel.ReconnectTime value here | 	// we manually override the tunnel.ReconnectTime value here | ||||||
| 	// this is so that we make the reconnects faster than the default 5s | 	// this is so that we make the reconnects faster than the default 5s | ||||||
| @@ -289,6 +275,7 @@ func TestReconnectTunnel(t *testing.T) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  | 	defer tunA.Close() | ||||||
|  |  | ||||||
| 	wait := make(chan bool) | 	wait := make(chan bool) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,14 +40,20 @@ func Extract(addr string) (string, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var addrs []net.Addr | 	var addrs []net.Addr | ||||||
|  | 	var loAddrs []net.Addr | ||||||
| 	for _, iface := range ifaces { | 	for _, iface := range ifaces { | ||||||
| 		ifaceAddrs, err := iface.Addrs() | 		ifaceAddrs, err := iface.Addrs() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			// ignore error, interface can dissapear from system | 			// ignore error, interface can dissapear from system | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  | 		if iface.Flags&net.FlagLoopback != 0 { | ||||||
|  | 			loAddrs = append(loAddrs, ifaceAddrs...) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		addrs = append(addrs, ifaceAddrs...) | 		addrs = append(addrs, ifaceAddrs...) | ||||||
| 	} | 	} | ||||||
|  | 	addrs = append(addrs, loAddrs...) | ||||||
|  |  | ||||||
| 	var ipAddr []byte | 	var ipAddr []byte | ||||||
| 	var publicIP []byte | 	var publicIP []byte | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ type Level int | |||||||
| const ( | const ( | ||||||
| 	LevelFatal Level = iota | 	LevelFatal Level = iota | ||||||
| 	LevelInfo | 	LevelInfo | ||||||
| 	LevelWarn | 	LevelError | ||||||
| 	LevelDebug | 	LevelDebug | ||||||
| 	LevelTrace | 	LevelTrace | ||||||
| ) | ) | ||||||
| @@ -29,16 +29,16 @@ var ( | |||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	switch os.Getenv("MICRO_LOG_LEVEL") { | 	switch os.Getenv("MICRO_LOG_LEVEL") { | ||||||
|  | 	case "trace": | ||||||
|  | 		level = LevelTrace | ||||||
| 	case "debug": | 	case "debug": | ||||||
| 		level = LevelDebug | 		level = LevelDebug | ||||||
| 	case "info": | 	case "info": | ||||||
| 		level = LevelInfo | 		level = LevelInfo | ||||||
| 	case "trace": | 	case "error": | ||||||
| 		level = LevelTrace | 		level = LevelError | ||||||
| 	case "fatal": | 	case "fatal": | ||||||
| 		level = LevelFatal | 		level = LevelFatal | ||||||
| 	case "warn": |  | ||||||
| 		level = LevelWarn |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -98,14 +98,14 @@ func Infof(format string, v ...interface{}) { | |||||||
| 	WithLevelf(LevelInfo, format, v...) | 	WithLevelf(LevelInfo, format, v...) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Warn provides warn level logging | // Error provides warn level logging | ||||||
| func Warn(v ...interface{}) { | func Error(v ...interface{}) { | ||||||
| 	WithLevel(LevelWarn, v...) | 	WithLevel(LevelError, v...) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Warnf provides warn level logging | // Errorf provides warn level logging | ||||||
| func Warnf(format string, v ...interface{}) { | func Errorf(format string, v ...interface{}) { | ||||||
| 	WithLevelf(LevelWarn, format, v...) | 	WithLevelf(LevelError, format, v...) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Fatal logs with Log and then exits with os.Exit(1) | // Fatal logs with Log and then exits with os.Exit(1) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user