mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-09-13 09:45:07 +03:00
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:
parent
cfa293d189
commit
d8a4000141
198 changed files with 8589 additions and 697 deletions
205
src/core/link.go
205
src/core/link.go
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue