2019-06-26 18:12:57 +03:00
|
|
|
package network
|
|
|
|
|
|
|
|
import (
|
2019-07-01 13:55:15 +03:00
|
|
|
"crypto/sha256"
|
|
|
|
"fmt"
|
2019-06-26 18:12:57 +03:00
|
|
|
"sync"
|
2019-07-01 13:55:15 +03:00
|
|
|
"time"
|
2019-06-26 18:12:57 +03:00
|
|
|
|
2019-07-01 13:55:15 +03:00
|
|
|
"github.com/google/uuid"
|
2019-06-26 18:12:57 +03:00
|
|
|
"github.com/micro/go-micro/config/options"
|
|
|
|
"github.com/micro/go-micro/network/proxy"
|
2019-07-02 00:59:11 +03:00
|
|
|
"github.com/micro/go-micro/network/proxy/mucp"
|
2019-07-01 13:55:15 +03:00
|
|
|
"github.com/micro/go-micro/network/resolver"
|
2019-06-26 21:28:30 +03:00
|
|
|
"github.com/micro/go-micro/network/router"
|
2019-07-01 13:55:15 +03:00
|
|
|
"github.com/micro/go-micro/registry"
|
|
|
|
|
|
|
|
pb "github.com/micro/go-micro/network/proto"
|
|
|
|
nreg "github.com/micro/go-micro/network/resolver/registry"
|
2019-06-26 18:12:57 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type network struct {
|
|
|
|
options.Options
|
|
|
|
|
2019-07-01 13:55:15 +03:00
|
|
|
// resolver use to connect to the network
|
|
|
|
resolver resolver.Resolver
|
|
|
|
|
|
|
|
// router used to find routes in the network
|
|
|
|
router router.Router
|
2019-06-26 18:12:57 +03:00
|
|
|
|
2019-07-01 13:55:15 +03:00
|
|
|
// proxy used to route through the network
|
|
|
|
proxy proxy.Proxy
|
2019-06-26 18:12:57 +03:00
|
|
|
|
|
|
|
// id of this network
|
|
|
|
id string
|
|
|
|
|
|
|
|
// links maintained for this network
|
2019-07-01 13:55:15 +03:00
|
|
|
// based on peers not nodes. maybe maintain
|
|
|
|
// node separately or note that links have nodes
|
2019-06-26 21:28:30 +03:00
|
|
|
mtx sync.RWMutex
|
2019-06-26 18:12:57 +03:00
|
|
|
links []Link
|
|
|
|
}
|
|
|
|
|
|
|
|
// network methods
|
|
|
|
|
2019-07-01 13:55:15 +03:00
|
|
|
// lease generates a new lease with a node id/address
|
|
|
|
// TODO: use a consensus mechanism, pool or some deterministic
|
2019-07-02 22:54:21 +03:00
|
|
|
// unique addressing method.
|
2019-07-03 21:26:24 +03:00
|
|
|
func (n *network) lease(muid string) *pb.Lease {
|
2019-07-01 13:55:15 +03:00
|
|
|
// create the id
|
|
|
|
id := uuid.New().String()
|
|
|
|
// create a timestamp
|
|
|
|
now := time.Now().UnixNano()
|
2019-07-02 22:54:21 +03:00
|
|
|
|
|
|
|
// create the address by hashing the id and timestamp
|
2019-07-01 13:55:15 +03:00
|
|
|
h := sha256.New()
|
|
|
|
h.Write([]byte(fmt.Sprintf("%s-%d\n", id, now)))
|
2019-07-02 22:54:21 +03:00
|
|
|
// magic new address
|
2019-07-01 13:55:15 +03:00
|
|
|
address := fmt.Sprintf("%x", h.Sum(nil))
|
|
|
|
|
|
|
|
// return the node
|
|
|
|
return &pb.Lease{
|
|
|
|
Id: id,
|
|
|
|
Timestamp: now,
|
|
|
|
Node: &pb.Node{
|
2019-07-03 21:26:24 +03:00
|
|
|
Muid: muid,
|
2019-07-01 13:55:15 +03:00
|
|
|
Id: id,
|
|
|
|
Address: address,
|
2019-07-02 22:54:21 +03:00
|
|
|
Network: n.id,
|
2019-07-01 13:55:15 +03:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// lookup returns a list of network records in priority order of local
|
|
|
|
func (n *network) lookup(r registry.Registry) []*resolver.Record {
|
|
|
|
// create a registry resolver to find local nodes
|
|
|
|
rr := nreg.Resolver{Registry: r}
|
|
|
|
|
|
|
|
// get all the nodes for the network that are local
|
|
|
|
localRecords, err := rr.Resolve("network:" + n.Id())
|
|
|
|
if err != nil {
|
|
|
|
// we're not in a good place here
|
|
|
|
}
|
|
|
|
|
|
|
|
// if its a local network we never try lookup anything else
|
|
|
|
if n.Id() == "local" {
|
|
|
|
return localRecords
|
|
|
|
}
|
|
|
|
|
|
|
|
// now resolve incrementally based on resolvers specified
|
|
|
|
networkRecords, err := n.resolver.Resolve(n.Id())
|
|
|
|
if err != nil {
|
|
|
|
// still not in a good place
|
|
|
|
}
|
|
|
|
|
|
|
|
// return aggregate records
|
|
|
|
return append(localRecords, networkRecords...)
|
|
|
|
}
|
|
|
|
|
2019-06-26 18:12:57 +03:00
|
|
|
func (n *network) Id() string {
|
|
|
|
return n.id
|
|
|
|
}
|
|
|
|
|
2019-07-01 13:55:15 +03:00
|
|
|
// Connect connects to the network and returns a new node.
|
|
|
|
// The node is the callers connection to the network. They
|
|
|
|
// should advertise this address to people. Anyone else
|
|
|
|
// on the network should be able to route to it.
|
2019-06-26 18:12:57 +03:00
|
|
|
func (n *network) Connect() (Node, error) {
|
2019-07-02 10:45:00 +03:00
|
|
|
return newNode(n)
|
2019-06-26 18:12:57 +03:00
|
|
|
}
|
|
|
|
|
2019-07-02 22:54:21 +03:00
|
|
|
// Peer is used to establish a link between two networks.
|
|
|
|
// e.g micro.mu connects to example.com and share routes
|
|
|
|
// This is done by creating a new node on both networks
|
|
|
|
// and creating a link between them.
|
2019-06-26 18:12:57 +03:00
|
|
|
func (n *network) Peer(Network) (Link, error) {
|
2019-07-01 13:55:15 +03:00
|
|
|
// New network was created using NewNetwork after receiving routes from a different node
|
|
|
|
|
|
|
|
// Connect to the new network and be assigned a node
|
|
|
|
|
|
|
|
// Transfer data between the networks
|
|
|
|
|
|
|
|
// take other resolver
|
|
|
|
// order: registry (local), ...resolver
|
|
|
|
// resolve the network
|
|
|
|
|
|
|
|
// periodically connect to nodes resolved in the network
|
|
|
|
// and add to the network links
|
2019-06-26 18:12:57 +03:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2019-07-02 00:59:11 +03:00
|
|
|
// newNetwork returns a new network interface
|
|
|
|
func newNetwork(opts ...options.Option) *network {
|
|
|
|
options := options.NewOptions(opts...)
|
|
|
|
|
2019-07-02 22:54:21 +03:00
|
|
|
// new network instance with defaults
|
2019-07-02 00:59:11 +03:00
|
|
|
net := &network{
|
2019-07-02 22:54:21 +03:00
|
|
|
Options: options,
|
|
|
|
id: DefaultId,
|
|
|
|
router: router.DefaultRouter,
|
|
|
|
proxy: new(mucp.Proxy),
|
|
|
|
resolver: new(nreg.Resolver),
|
2019-07-02 00:59:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// get network id
|
|
|
|
id, ok := options.Values().Get("network.id")
|
|
|
|
if ok {
|
|
|
|
net.id = id.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get router
|
|
|
|
r, ok := options.Values().Get("network.router")
|
|
|
|
if ok {
|
|
|
|
net.router = r.(router.Router)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get proxy
|
|
|
|
p, ok := options.Values().Get("network.proxy")
|
|
|
|
if ok {
|
|
|
|
net.proxy = p.(proxy.Proxy)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get resolver
|
|
|
|
res, ok := options.Values().Get("network.resolver")
|
|
|
|
if ok {
|
|
|
|
net.resolver = res.(resolver.Resolver)
|
|
|
|
}
|
|
|
|
|
|
|
|
return net
|
|
|
|
}
|