1. added multipath protocol and schema suport

2. added SCTP protocol and schema support
3. added set of NAS models support (Asustor, ReadyNAS, Drobo, QNAP, WD, Synology, Terramaster)
4. moved to fc00::/7 private segment
5. added Windows, MacOS and Linux UI for peers edit and current status
This commit is contained in:
vadym 2022-10-27 22:03:37 +03:00
parent cfa293d189
commit d8a4000141
198 changed files with 8589 additions and 697 deletions

View file

@ -10,191 +10,73 @@ import (
"net/url"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/Arceliar/phony"
"github.com/yggdrasil-network/yggdrasil-go/src/address"
)
"sync/atomic"
type links struct {
phony.Inbox
core *Core
tcp *linkTCP // TCP interface support
tls *linkTLS // TLS interface support
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
_links map[linkInfo]*link // *link is nil if connection in progress
}
"github.com/Arceliar/phony"
"github.com/RiV-chain/RiV-mesh/src/address"
//"github.com/Arceliar/phony" // TODO? use instead of mutexes
)
// linkInfo is used as a map key
type linkInfo struct {
linkType string // Type of link, e.g. TCP, AWDL
local string // Local name or address
remote string // Remote name or address
linkType string // Type of link, e.g. TCP, AWDL
local string // Local name or address
remote string // Remote name or address
}
type link struct {
lname string
links *links
conn *linkConn
options linkOptions
info linkInfo
incoming bool
force bool
lname string
links *links
conn *linkConn
options linkOptions
info linkInfo
incoming bool
force bool
}
type linkOptions struct {
pinnedEd25519Keys map[keyArray]struct{}
pinnedEd25519Keys map[keyArray]struct{}
priority uint8
}
type Listener struct {
net.Listener
closed chan struct{}
net.Listener
closed chan struct{}
}
func (l *Listener) Close() error {
err := l.Listener.Close()
<-l.closed
return err
}
func (l *links) init(c *Core) error {
l.core = c
l.tcp = l.newLinkTCP()
l.tls = l.newLinkTLS(l.tcp)
l.unix = l.newLinkUNIX()
l.socks = l.newLinkSOCKS()
l._links = make(map[linkInfo]*link)
var listeners []ListenAddress
phony.Block(c, func() {
listeners = make([]ListenAddress, 0, len(c.config._listeners))
for listener := range c.config._listeners {
listeners = append(listeners, listener)
}
})
return nil
err := l.Listener.Close()
<-l.closed
return err
}
func (l *links) shutdown() {
phony.Block(l.tcp, func() {
for l := range l.tcp._listeners {
_ = l.Close()
}
})
phony.Block(l.tls, func() {
for l := range l.tls._listeners {
_ = l.Close()
}
})
phony.Block(l.unix, func() {
for l := range l.unix._listeners {
_ = l.Close()
}
})
phony.Block(l.tcp, func() {
for l := range l.tcp._listeners {
_ = l.Close()
}
})
phony.Block(l.tls, func() {
for l := range l.tls._listeners {
_ = l.Close()
}
})
phony.Block(l.unix, func() {
for l := range l.unix._listeners {
_ = l.Close()
}
})
}
func (l *links) isConnectedTo(info linkInfo) bool {
var isConnected bool
phony.Block(l, func() {
_, isConnected = l._links[info]
})
return isConnected
}
func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
info := linkInfoFor(u.Scheme, sintf, u.Host)
if l.isConnectedTo(info) {
return info, nil
}
options := linkOptions{
pinnedEd25519Keys: map[keyArray]struct{}{},
}
for _, pubkey := range u.Query()["key"] {
sigPub, err := hex.DecodeString(pubkey)
if err != nil {
return info, fmt.Errorf("pinned key contains invalid hex characters")
}
var sigPubKey keyArray
copy(sigPubKey[:], sigPub)
options.pinnedEd25519Keys[sigPubKey] = struct{}{}
}
if p := u.Query().Get("priority"); p != "" {
pi, err := strconv.ParseUint(p, 10, 8)
if err != nil {
return info, fmt.Errorf("priority invalid: %w", err)
}
options.priority = uint8(pi)
}
switch info.linkType {
case "tcp":
go func() {
if err := l.tcp.dial(u, options, sintf); err != nil && err != io.EOF {
l.core.log.Warnf("Failed to dial TCP %s: %s\n", u.Host, err)
}
}()
case "socks":
go func() {
if err := l.socks.dial(u, options); err != nil && err != io.EOF {
l.core.log.Warnf("Failed to dial SOCKS %s: %s\n", u.Host, err)
}
}()
case "tls":
// SNI headers must contain hostnames and not IP addresses, so we must make sure
// that we do not populate the SNI with an IP literal. We do this by splitting
// the host-port combo from the query option and then seeing if it parses to an
// IP address successfully or not.
var tlsSNI string
if sni := u.Query().Get("sni"); sni != "" {
if net.ParseIP(sni) == nil {
tlsSNI = sni
}
}
// If the SNI is not configured still because the above failed then we'll try
// again but this time we'll use the host part of the peering URI instead.
if tlsSNI == "" {
if host, _, err := net.SplitHostPort(u.Host); err == nil && net.ParseIP(host) == nil {
tlsSNI = host
}
}
go func() {
if err := l.tls.dial(u, options, sintf, tlsSNI); err != nil && err != io.EOF {
l.core.log.Warnf("Failed to dial TLS %s: %s\n", u.Host, err)
}
}()
case "unix":
go func() {
if err := l.unix.dial(u, options, sintf); err != nil && err != io.EOF {
l.core.log.Warnf("Failed to dial UNIX %s: %s\n", u.Host, err)
}
}()
default:
return info, errors.New("unknown call scheme: " + u.Scheme)
}
return info, nil
}
func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
var listener *Listener
var err error
switch u.Scheme {
case "tcp":
listener, err = l.tcp.listen(u, sintf)
case "tls":
listener, err = l.tls.listen(u, sintf)
case "unix":
listener, err = l.unix.listen(u, sintf)
default:
return nil, fmt.Errorf("unrecognised scheme %q", u.Scheme)
}
return listener, err
var isConnected bool
phony.Block(l, func() {
_, isConnected = l._links[info]
})
return isConnected
}
func (l *links) create(conn net.Conn, name string, info linkInfo, incoming, force bool, options linkOptions) error {
@ -329,6 +211,9 @@ func (intf *link) close() error {
}
func linkInfoFor(linkType, sintf, remote string) linkInfo {
if h, _, err := net.SplitHostPort(remote); err == nil {
remote = h
}
return linkInfo{
linkType: linkType,
local: sintf,