This commit is contained in:
Adam Ierymenko 2019-09-26 09:34:31 -07:00
commit 7061f13b24
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
10 changed files with 229 additions and 43 deletions

View file

@ -96,6 +96,7 @@ type APIStatus struct {
// APINetwork is the object returned by API network inquiries
type APINetwork struct {
ID NetworkID
Config *NetworkConfig
Settings *NetworkLocalSettings
MulticastSubscriptions []*MulticastGroup
@ -104,6 +105,20 @@ type APINetwork struct {
TapDeviceEnabled bool
}
func apiNetworkFromNetwork(n *Network) *APINetwork {
var nn APINetwork
nn.ID = n.ID()
c := n.Config()
nn.Config = &c
ls := n.LocalSettings()
nn.Settings = &ls
nn.MulticastSubscriptions = n.MulticastSubscriptions()
nn.TapDeviceType = n.Tap().Type()
nn.TapDeviceName = n.Tap().DeviceName()
nn.TapDeviceEnabled = n.Tap().Enabled()
return &nn
}
func apiSetStandardHeaders(out http.ResponseWriter) {
now := time.Now().UTC()
h := out.Header()
@ -215,6 +230,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
if req.Method == http.MethodPost || req.Method == http.MethodPut {
var c LocalConfig
if apiReadObj(out, req, &c) == nil {
node.SetLocalConfig(&c)
apiSendObj(out, req, http.StatusOK, node.LocalConfig())
}
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
@ -279,12 +295,40 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
if req.Method == http.MethodPost || req.Method == http.MethodPut {
if queriedID == 0 {
apiSendObj(out, req, http.StatusBadRequest, nil)
} else {
var nw APINetwork
if apiReadObj(out, req, &nw) == nil {
n := node.GetNetwork(nw.ID)
if n == nil {
n, err := node.Join(nw.ID, nw.Settings, nil)
if err != nil {
apiSendObj(out, req, http.StatusBadRequest, nil)
} else {
apiSendObj(out, req, http.StatusOK, apiNetworkFromNetwork(n))
}
} else {
if nw.Settings != nil {
n.SetLocalSettings(nw.Settings)
}
apiSendObj(out, req, http.StatusOK, apiNetworkFromNetwork(n))
}
}
}
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
networks := node.Networks()
if queriedID == 0 { // no queried ID lists all networks
networks := node.Networks()
apiSendObj(out, req, http.StatusOK, networks)
nws := make([]*APINetwork, 0, len(networks))
for _, nw := range networks {
nws = append(nws, apiNetworkFromNetwork(nw))
}
apiSendObj(out, req, http.StatusOK, nws)
} else {
for _, nw := range networks {
if nw.ID() == queriedID {
apiSendObj(out, req, http.StatusOK, apiNetworkFromNetwork(nw))
break
}
}
}
} else {
out.Header().Set("Allow", "GET, HEAD, PUT, POST")

View file

@ -194,6 +194,13 @@ func (n *Network) Config() NetworkConfig {
// SetLocalSettings modifies this network's local settings
func (n *Network) SetLocalSettings(ls *NetworkLocalSettings) { n.updateConfig(nil, ls) }
// LocalSettings gets this network's current local settings
func (n *Network) LocalSettings() NetworkLocalSettings {
n.configLock.RLock()
defer n.configLock.RUnlock()
return n.settings
}
// MulticastSubscribe subscribes to a multicast group
func (n *Network) MulticastSubscribe(mg *MulticastGroup) {
n.node.log.Printf("%.16x joined multicast group %s", mg.String())

View file

@ -464,10 +464,13 @@ func (n *Node) SetLocalConfig(lc *LocalConfig) (restartRequired bool, err error)
// Join joins a network
// If tap is nil, the default system tap for this OS/platform is used (if available).
func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
func (n *Node) Join(nwid NetworkID, settings *NetworkLocalSettings, tap Tap) (*Network, error) {
n.networksLock.RLock()
if nw, have := n.networks[NetworkID(nwid)]; have {
if nw, have := n.networks[nwid]; have {
n.log.Printf("join network %.16x ignored: already a member", nwid)
if settings != nil {
nw.SetLocalSettings(settings)
}
return nw, nil
}
n.networksLock.RUnlock()
@ -488,8 +491,11 @@ func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
return nil, err
}
n.networksLock.Lock()
n.networks[NetworkID(nwid)] = nw
n.networks[nwid] = nw
n.networksLock.Unlock()
if settings != nil {
nw.SetLocalSettings(settings)
}
return nw, nil
}
@ -504,6 +510,14 @@ func (n *Node) Leave(nwid uint64) error {
return nil
}
// GetNetwork looks up a network by ID or returns nil if not joined
func (n *Node) GetNetwork(nwid NetworkID) *Network {
n.networksLock.RLock()
nw := n.networks[nwid]
n.networksLock.RUnlock()
return nw
}
// Networks returns a list of networks that this node has joined
func (n *Node) Networks() []*Network {
var nws []*Network
@ -613,30 +627,35 @@ func (n *Node) Peers() []*Peer {
p2.Paths = make([]Path, 0, int(p.pathCount))
for j := uintptr(0); j < uintptr(p.pathCount); j++ {
pt := &p.paths[j]
a := sockaddrStorageToUDPAddr(&pt.address)
if a != nil {
p2.Paths = append(p2.Paths, Path{
IP: a.IP,
Port: a.Port,
LastSend: int64(pt.lastSend),
LastReceive: int64(pt.lastReceive),
TrustedPathID: uint64(pt.trustedPathId),
Latency: float32(pt.latency),
PacketDelayVariance: float32(pt.packetDelayVariance),
ThroughputDisturbCoeff: float32(pt.throughputDisturbCoeff),
PacketErrorRatio: float32(pt.packetErrorRatio),
PacketLossRatio: float32(pt.packetLossRatio),
Stability: float32(pt.stability),
Throughput: uint64(pt.throughput),
MaxThroughput: uint64(pt.maxThroughput),
Allocation: float32(pt.allocation),
})
if pt.alive != 0 {
a := sockaddrStorageToUDPAddr(&pt.address)
if a != nil {
p2.Paths = append(p2.Paths, Path{
IP: a.IP,
Port: a.Port,
LastSend: int64(pt.lastSend),
LastReceive: int64(pt.lastReceive),
TrustedPathID: uint64(pt.trustedPathId),
Latency: float32(pt.latency),
PacketDelayVariance: float32(pt.packetDelayVariance),
ThroughputDisturbCoeff: float32(pt.throughputDisturbCoeff),
PacketErrorRatio: float32(pt.packetErrorRatio),
PacketLossRatio: float32(pt.packetLossRatio),
Stability: float32(pt.stability),
Throughput: uint64(pt.throughput),
MaxThroughput: uint64(pt.maxThroughput),
Allocation: float32(pt.allocation),
})
}
}
}
sort.Slice(p2.Paths, func(a, b int) bool { return p2.Paths[a].LastReceive < p2.Paths[b].LastReceive })
p2.Clock = TimeMs()
peers = append(peers, p2)
}
C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(pl))
}
sort.Slice(peers, func(a, b int) bool { return peers[a].Address < peers[b].Address })
return peers
}

View file

@ -20,4 +20,5 @@ type Peer struct {
Latency int
Role int
Paths []Path
Clock int64
}