Yggdrasil demo updates (#1241)
* PerformServersAlive in PerformBroadcastEDU * Don't double-pointer * More reliable QUIC session handling * Direct peer lookup, other tweaks * Tweaks * Try to wake up queues on incoming QUIC session * Set session callbak on gobind build * Fix incoming session storage * Stateless reset, other tweaks * Reset sessions when coordinates change * Disable HTTP connection reuse, tweak timeoutsmain
parent
642f9cb964
commit
b7491aae03
|
@ -25,7 +25,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/userapi"
|
"github.com/matrix-org/dendrite/userapi"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"go.uber.org/atomic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DendriteMonolith struct {
|
type DendriteMonolith struct {
|
||||||
|
@ -34,8 +33,6 @@ type DendriteMonolith struct {
|
||||||
StorageDirectory string
|
StorageDirectory string
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
httpListening atomic.Bool
|
|
||||||
yggListening atomic.Bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DendriteMonolith) BaseURL() string {
|
func (m *DendriteMonolith) BaseURL() string {
|
||||||
|
@ -46,6 +43,10 @@ func (m *DendriteMonolith) PeerCount() int {
|
||||||
return m.YggdrasilNode.PeerCount()
|
return m.YggdrasilNode.PeerCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *DendriteMonolith) SessionCount() int {
|
||||||
|
return m.YggdrasilNode.SessionCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *DendriteMonolith) SetMulticastEnabled(enabled bool) {
|
func (m *DendriteMonolith) SetMulticastEnabled(enabled bool) {
|
||||||
m.YggdrasilNode.SetMulticastEnabled(enabled)
|
m.YggdrasilNode.SetMulticastEnabled(enabled)
|
||||||
}
|
}
|
||||||
|
@ -86,7 +87,7 @@ func (m *DendriteMonolith) Start() {
|
||||||
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
|
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
|
||||||
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
||||||
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||||
cfg.Matrix.FederationMaxRetries = 6
|
cfg.Matrix.FederationMaxRetries = 8
|
||||||
cfg.Kafka.UseNaffka = true
|
cfg.Kafka.UseNaffka = true
|
||||||
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
||||||
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
||||||
|
@ -98,7 +99,7 @@ func (m *DendriteMonolith) Start() {
|
||||||
cfg.Database.SyncAPI = config.DataSource(fmt.Sprintf("file:%s/dendrite-syncapi.db", m.StorageDirectory))
|
cfg.Database.SyncAPI = config.DataSource(fmt.Sprintf("file:%s/dendrite-syncapi.db", m.StorageDirectory))
|
||||||
cfg.Database.RoomServer = config.DataSource(fmt.Sprintf("file:%s/dendrite-roomserver.db", m.StorageDirectory))
|
cfg.Database.RoomServer = config.DataSource(fmt.Sprintf("file:%s/dendrite-roomserver.db", m.StorageDirectory))
|
||||||
cfg.Database.ServerKey = config.DataSource(fmt.Sprintf("file:%s/dendrite-serverkey.db", m.StorageDirectory))
|
cfg.Database.ServerKey = config.DataSource(fmt.Sprintf("file:%s/dendrite-serverkey.db", m.StorageDirectory))
|
||||||
cfg.Database.E2EKey = config.DataSource(fmt.Sprintf("file:%s/dendrite-e2ekey.db", m.StorageDirectory))
|
cfg.Database.E2EKey = config.DataSource(fmt.Sprintf("file:%s/dendrite-keyserver.db", m.StorageDirectory))
|
||||||
cfg.Database.FederationSender = config.DataSource(fmt.Sprintf("file:%s/dendrite-federationsender.db", m.StorageDirectory))
|
cfg.Database.FederationSender = config.DataSource(fmt.Sprintf("file:%s/dendrite-federationsender.db", m.StorageDirectory))
|
||||||
cfg.Database.AppService = config.DataSource(fmt.Sprintf("file:%s/dendrite-appservice.db", m.StorageDirectory))
|
cfg.Database.AppService = config.DataSource(fmt.Sprintf("file:%s/dendrite-appservice.db", m.StorageDirectory))
|
||||||
cfg.Database.CurrentState = config.DataSource(fmt.Sprintf("file:%s/dendrite-currentstate.db", m.StorageDirectory))
|
cfg.Database.CurrentState = config.DataSource(fmt.Sprintf("file:%s/dendrite-currentstate.db", m.StorageDirectory))
|
||||||
|
@ -136,6 +137,18 @@ func (m *DendriteMonolith) Start() {
|
||||||
base, federation, rsAPI, stateAPI, keyRing,
|
base, federation, rsAPI, stateAPI, keyRing,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ygg.SetSessionFunc(func(address string) {
|
||||||
|
req := &api.PerformServersAliveRequest{
|
||||||
|
Servers: []gomatrixserverlib.ServerName{
|
||||||
|
gomatrixserverlib.ServerName(address),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res := &api.PerformServersAliveResponse{}
|
||||||
|
if err := fsAPI.PerformServersAlive(context.TODO(), req, res); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to send wake-up message to newly connected node")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// The underlying roomserver implementation needs to be able to call the fedsender.
|
// The underlying roomserver implementation needs to be able to call the fedsender.
|
||||||
// This is different to rsAPI which can be the http client which doesn't need this dependency
|
// This is different to rsAPI which can be the http client which doesn't need this dependency
|
||||||
rsAPI.SetFederationSenderAPI(fsAPI)
|
rsAPI.SetFederationSenderAPI(fsAPI)
|
||||||
|
@ -175,9 +188,9 @@ func (m *DendriteMonolith) Start() {
|
||||||
m.httpServer = &http.Server{
|
m.httpServer = &http.Server{
|
||||||
Addr: ":0",
|
Addr: ":0",
|
||||||
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
|
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
|
||||||
ReadTimeout: 30 * time.Second,
|
ReadTimeout: 10 * time.Second,
|
||||||
WriteTimeout: 30 * time.Second,
|
WriteTimeout: 10 * time.Second,
|
||||||
IdleTimeout: 60 * time.Second,
|
IdleTimeout: 30 * time.Second,
|
||||||
BaseContext: func(_ net.Listener) context.Context {
|
BaseContext: func(_ net.Listener) context.Context {
|
||||||
return context.Background()
|
return context.Background()
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,7 +72,7 @@ func main() {
|
||||||
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
|
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
|
||||||
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
||||||
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||||
cfg.Matrix.FederationMaxRetries = 6
|
cfg.Matrix.FederationMaxRetries = 8
|
||||||
cfg.Kafka.UseNaffka = true
|
cfg.Kafka.UseNaffka = true
|
||||||
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
||||||
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
||||||
|
@ -83,7 +83,7 @@ func main() {
|
||||||
cfg.Database.SyncAPI = config.DataSource(fmt.Sprintf("file:%s-syncapi.db", *instanceName))
|
cfg.Database.SyncAPI = config.DataSource(fmt.Sprintf("file:%s-syncapi.db", *instanceName))
|
||||||
cfg.Database.RoomServer = config.DataSource(fmt.Sprintf("file:%s-roomserver.db", *instanceName))
|
cfg.Database.RoomServer = config.DataSource(fmt.Sprintf("file:%s-roomserver.db", *instanceName))
|
||||||
cfg.Database.ServerKey = config.DataSource(fmt.Sprintf("file:%s-serverkey.db", *instanceName))
|
cfg.Database.ServerKey = config.DataSource(fmt.Sprintf("file:%s-serverkey.db", *instanceName))
|
||||||
cfg.Database.E2EKey = config.DataSource(fmt.Sprintf("file:%s-e2ekey.db", *instanceName))
|
cfg.Database.E2EKey = config.DataSource(fmt.Sprintf("file:%s-keyserver.db", *instanceName))
|
||||||
cfg.Database.FederationSender = config.DataSource(fmt.Sprintf("file:%s-federationsender.db", *instanceName))
|
cfg.Database.FederationSender = config.DataSource(fmt.Sprintf("file:%s-federationsender.db", *instanceName))
|
||||||
cfg.Database.AppService = config.DataSource(fmt.Sprintf("file:%s-appservice.db", *instanceName))
|
cfg.Database.AppService = config.DataSource(fmt.Sprintf("file:%s-appservice.db", *instanceName))
|
||||||
cfg.Database.CurrentState = config.DataSource(fmt.Sprintf("file:%s-currentstate.db", *instanceName))
|
cfg.Database.CurrentState = config.DataSource(fmt.Sprintf("file:%s-currentstate.db", *instanceName))
|
||||||
|
@ -122,6 +122,18 @@ func main() {
|
||||||
base, federation, rsAPI, stateAPI, keyRing,
|
base, federation, rsAPI, stateAPI, keyRing,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ygg.SetSessionFunc(func(address string) {
|
||||||
|
req := &api.PerformServersAliveRequest{
|
||||||
|
Servers: []gomatrixserverlib.ServerName{
|
||||||
|
gomatrixserverlib.ServerName(address),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res := &api.PerformServersAliveResponse{}
|
||||||
|
if err := fsAPI.PerformServersAlive(context.TODO(), req, res); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to send wake-up message to newly connected node")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
rsComponent.SetFederationSenderAPI(fsAPI)
|
rsComponent.SetFederationSenderAPI(fsAPI)
|
||||||
|
|
||||||
embed.Embed(base.BaseMux, *instancePort, "Yggdrasil Demo")
|
embed.Embed(base.BaseMux, *instancePort, "Yggdrasil Demo")
|
||||||
|
@ -162,9 +174,9 @@ func main() {
|
||||||
httpServer := &http.Server{
|
httpServer := &http.Server{
|
||||||
Addr: ":0",
|
Addr: ":0",
|
||||||
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
|
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
|
||||||
ReadTimeout: 15 * time.Second,
|
ReadTimeout: 10 * time.Second,
|
||||||
WriteTimeout: 45 * time.Second,
|
WriteTimeout: 10 * time.Second,
|
||||||
IdleTimeout: 60 * time.Second,
|
IdleTimeout: 30 * time.Second,
|
||||||
BaseContext: func(_ net.Listener) context.Context {
|
BaseContext: func(_ net.Listener) context.Context {
|
||||||
return context.Background()
|
return context.Background()
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,9 +24,11 @@ func (n *Node) CreateClient(
|
||||||
tr.RegisterProtocol(
|
tr.RegisterProtocol(
|
||||||
"matrix", &yggroundtripper{
|
"matrix", &yggroundtripper{
|
||||||
inner: &http.Transport{
|
inner: &http.Transport{
|
||||||
TLSHandshakeTimeout: 20 * time.Second,
|
MaxIdleConns: -1,
|
||||||
|
MaxIdleConnsPerHost: -1,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ResponseHeaderTimeout: 10 * time.Second,
|
ResponseHeaderTimeout: 10 * time.Second,
|
||||||
IdleConnTimeout: 60 * time.Second,
|
IdleConnTimeout: 30 * time.Second,
|
||||||
DialContext: n.DialerContext,
|
DialContext: n.DialerContext,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -41,9 +43,11 @@ func (n *Node) CreateFederationClient(
|
||||||
tr.RegisterProtocol(
|
tr.RegisterProtocol(
|
||||||
"matrix", &yggroundtripper{
|
"matrix", &yggroundtripper{
|
||||||
inner: &http.Transport{
|
inner: &http.Transport{
|
||||||
TLSHandshakeTimeout: 20 * time.Second,
|
MaxIdleConns: -1,
|
||||||
|
MaxIdleConnsPerHost: -1,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ResponseHeaderTimeout: 10 * time.Second,
|
ResponseHeaderTimeout: 10 * time.Second,
|
||||||
IdleConnTimeout: 60 * time.Second,
|
IdleConnTimeout: 30 * time.Second,
|
||||||
DialContext: n.DialerContext,
|
DialContext: n.DialerContext,
|
||||||
TLSClientConfig: n.tlsConfig,
|
TLSClientConfig: n.tlsConfig,
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
|
||||||
yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
yggdrasilmulticast "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
yggdrasilmulticast "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||||
|
@ -41,17 +42,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
core *yggdrasil.Core
|
core *yggdrasil.Core
|
||||||
config *yggdrasilconfig.NodeConfig
|
config *yggdrasilconfig.NodeConfig
|
||||||
state *yggdrasilconfig.NodeState
|
state *yggdrasilconfig.NodeState
|
||||||
multicast *yggdrasilmulticast.Multicast
|
multicast *yggdrasilmulticast.Multicast
|
||||||
log *gologme.Logger
|
log *gologme.Logger
|
||||||
listener quic.Listener
|
listener quic.Listener
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
quicConfig *quic.Config
|
quicConfig *quic.Config
|
||||||
sessions sync.Map // string -> quic.Session
|
sessions sync.Map // string -> *session
|
||||||
incoming chan QUICStream
|
sessionCount atomic.Uint32
|
||||||
NewSession func(remote gomatrixserverlib.ServerName)
|
sessionFunc func(address string)
|
||||||
|
coords sync.Map // string -> yggdrasil.Coords
|
||||||
|
incoming chan QUICStream
|
||||||
|
NewSession func(remote gomatrixserverlib.ServerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) Dialer(_, address string) (net.Conn, error) {
|
func (n *Node) Dialer(_, address string) (net.Conn, error) {
|
||||||
|
@ -90,6 +94,19 @@ func Setup(instanceName, storageDirectory string) (*Node, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.core.SetCoordChangeCallback(func(old, new yggdrasil.Coords) {
|
||||||
|
fmt.Println("COORDINATE CHANGE!")
|
||||||
|
fmt.Println("Old:", old)
|
||||||
|
fmt.Println("New:", new)
|
||||||
|
n.sessions.Range(func(k, v interface{}) bool {
|
||||||
|
if s, ok := v.(*session); ok {
|
||||||
|
fmt.Println("Killing session", k)
|
||||||
|
s.kill()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
n.config.Peers = []string{}
|
n.config.Peers = []string{}
|
||||||
n.config.AdminListen = "none"
|
n.config.AdminListen = "none"
|
||||||
n.config.MulticastInterfaces = []string{}
|
n.config.MulticastInterfaces = []string{}
|
||||||
|
@ -124,8 +141,9 @@ func Setup(instanceName, storageDirectory string) (*Node, error) {
|
||||||
MaxIncomingUniStreams: 0,
|
MaxIncomingUniStreams: 0,
|
||||||
KeepAlive: true,
|
KeepAlive: true,
|
||||||
MaxIdleTimeout: time.Minute * 30,
|
MaxIdleTimeout: time.Minute * 30,
|
||||||
HandshakeTimeout: time.Second * 30,
|
HandshakeTimeout: time.Second * 15,
|
||||||
}
|
}
|
||||||
|
copy(n.quicConfig.StatelessResetKey, n.EncryptionPublicKey())
|
||||||
|
|
||||||
n.log.Println("Public curve25519:", n.core.EncryptionPublicKey())
|
n.log.Println("Public curve25519:", n.core.EncryptionPublicKey())
|
||||||
n.log.Println("Public ed25519:", n.core.SigningPublicKey())
|
n.log.Println("Public ed25519:", n.core.SigningPublicKey())
|
||||||
|
@ -173,17 +191,25 @@ func (n *Node) SigningPrivateKey() ed25519.PrivateKey {
|
||||||
return ed25519.PrivateKey(privBytes)
|
return ed25519.PrivateKey(privBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) SetSessionFunc(f func(address string)) {
|
||||||
|
n.sessionFunc = f
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) PeerCount() int {
|
func (n *Node) PeerCount() int {
|
||||||
return len(n.core.GetPeers()) - 1
|
return len(n.core.GetPeers()) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) SessionCount() int {
|
||||||
|
return int(n.sessionCount.Load())
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) KnownNodes() []gomatrixserverlib.ServerName {
|
func (n *Node) KnownNodes() []gomatrixserverlib.ServerName {
|
||||||
nodemap := map[string]struct{}{
|
nodemap := map[string]struct{}{
|
||||||
"b5ae50589e50991dd9dd7d59c5c5f7a4521e8da5b603b7f57076272abc58b374": struct{}{},
|
"b5ae50589e50991dd9dd7d59c5c5f7a4521e8da5b603b7f57076272abc58b374": {},
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
for _, peer := range n.core.GetSwitchPeers() {
|
for _, peer := range n.core.GetSwitchPeers() {
|
||||||
nodemap[hex.EncodeToString(peer.SigningKey[:])] = struct{}{}
|
nodemap[hex.EncodeToString(peer.PublicKey[:])] = struct{}{}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
n.sessions.Range(func(_, v interface{}) bool {
|
n.sessions.Range(func(_, v interface{}) bool {
|
||||||
|
|
|
@ -31,8 +31,32 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type session struct {
|
||||||
|
node *Node
|
||||||
|
session quic.Session
|
||||||
|
address string
|
||||||
|
context context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) newSession(sess quic.Session, address string) *session {
|
||||||
|
ctx, cancel := context.WithCancel(context.TODO())
|
||||||
|
return &session{
|
||||||
|
node: n,
|
||||||
|
session: sess,
|
||||||
|
address: address,
|
||||||
|
context: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *session) kill() {
|
||||||
|
s.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) listenFromYgg() {
|
func (n *Node) listenFromYgg() {
|
||||||
var err error
|
var err error
|
||||||
n.listener, err = quic.Listen(
|
n.listener, err = quic.Listen(
|
||||||
|
@ -55,22 +79,31 @@ func (n *Node) listenFromYgg() {
|
||||||
_ = session.CloseWithError(0, "expected a peer certificate")
|
_ = session.CloseWithError(0, "expected a peer certificate")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
address := session.ConnectionState().PeerCertificates[0].Subject.CommonName
|
address := session.ConnectionState().PeerCertificates[0].DNSNames[0]
|
||||||
n.log.Infoln("Accepted connection from", address)
|
n.log.Infoln("Accepted connection from", address)
|
||||||
go n.listenFromQUIC(session, address)
|
go n.newSession(session, address).listenFromQUIC()
|
||||||
|
go n.sessionFunc(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) listenFromQUIC(session quic.Session, address string) {
|
func (s *session) listenFromQUIC() {
|
||||||
n.sessions.Store(address, session)
|
if existing, ok := s.node.sessions.Load(s.address); ok {
|
||||||
defer n.sessions.Delete(address)
|
if existingSession, ok := existing.(*session); ok {
|
||||||
|
fmt.Println("Killing existing session to replace", s.address)
|
||||||
|
existingSession.kill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.node.sessionCount.Inc()
|
||||||
|
s.node.sessions.Store(s.address, s)
|
||||||
|
defer s.node.sessions.Delete(s.address)
|
||||||
|
defer s.node.sessionCount.Dec()
|
||||||
for {
|
for {
|
||||||
st, err := session.AcceptStream(context.TODO())
|
st, err := s.session.AcceptStream(s.context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.log.Println("session.AcceptStream:", err)
|
s.node.log.Println("session.AcceptStream:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n.incoming <- QUICStream{st, session}
|
s.node.incoming <- QUICStream{st, s.session}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,53 +128,124 @@ func (n *Node) Dial(network, address string) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements http.Transport.DialContext
|
// Implements http.Transport.DialContext
|
||||||
|
// nolint:gocyclo
|
||||||
func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
s, ok1 := n.sessions.Load(address)
|
s, ok1 := n.sessions.Load(address)
|
||||||
session, ok2 := s.(quic.Session)
|
session, ok2 := s.(*session)
|
||||||
if !ok1 || !ok2 || (ok1 && ok2 && session.ConnectionState().HandshakeComplete) {
|
if !ok1 || !ok2 {
|
||||||
dest, err := hex.DecodeString(address)
|
// First of all, check if we think we know the coords of this
|
||||||
if err != nil {
|
// node. If we do then we'll try to dial to it directly. This
|
||||||
return nil, err
|
// will either succeed or fail.
|
||||||
}
|
if v, ok := n.coords.Load(address); ok {
|
||||||
if len(dest) != crypto.BoxPubKeyLen {
|
coords, ok := v.(yggdrasil.Coords)
|
||||||
return nil, errors.New("invalid key length supplied")
|
if !ok {
|
||||||
}
|
n.coords.Delete(address)
|
||||||
var pubKey crypto.BoxPubKey
|
return nil, errors.New("should have found yggdrasil.Coords but didn't")
|
||||||
copy(pubKey[:], dest)
|
}
|
||||||
nodeID := crypto.GetNodeID(&pubKey)
|
n.log.Infof("Coords %s for %q cached, trying to dial", coords.String(), address)
|
||||||
nodeMask := &crypto.NodeID{}
|
var err error
|
||||||
for i := range nodeMask {
|
// We think we know the coords. Try to dial the node.
|
||||||
nodeMask[i] = 0xFF
|
if session, err = n.tryDial(address, coords); err != nil {
|
||||||
|
// We thought we knew the coords but it didn't result
|
||||||
|
// in a successful dial. Nuke them from the cache.
|
||||||
|
n.coords.Delete(address)
|
||||||
|
n.log.Infof("Cached coords %s for %q failed", coords.String(), address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Resolving coords")
|
// We either don't know the coords for the node, or we failed
|
||||||
coords, err := n.core.Resolve(nodeID, nodeMask)
|
// to dial it before, in which case try to resolve the coords.
|
||||||
if err != nil {
|
if _, ok := n.coords.Load(address); !ok {
|
||||||
return nil, fmt.Errorf("n.core.Resolve: %w", err)
|
var coords yggdrasil.Coords
|
||||||
}
|
var err error
|
||||||
fmt.Println("Found coords:", coords)
|
|
||||||
fmt.Println("Dialling")
|
|
||||||
|
|
||||||
session, err = quic.Dial(
|
// First look and see if the node is something that we already
|
||||||
n.core, // yggdrasil.PacketConn
|
// know about from our direct switch peers.
|
||||||
coords, // dial address
|
for _, peer := range n.core.GetSwitchPeers() {
|
||||||
address, // dial SNI
|
if peer.PublicKey.String() == address {
|
||||||
n.tlsConfig, // TLS config
|
coords = peer.Coords
|
||||||
n.quicConfig, // QUIC config
|
n.log.Infof("%q is a direct peer, coords are %s", address, coords.String())
|
||||||
)
|
n.coords.Store(address, coords)
|
||||||
if err != nil {
|
break
|
||||||
n.log.Println("n.dialer.DialContext:", err)
|
}
|
||||||
return nil, err
|
}
|
||||||
|
|
||||||
|
// If it isn' a node that we know directly then try to search
|
||||||
|
// the network.
|
||||||
|
if coords == nil {
|
||||||
|
n.log.Infof("Searching for coords for %q", address)
|
||||||
|
dest, derr := hex.DecodeString(address)
|
||||||
|
if derr != nil {
|
||||||
|
return nil, derr
|
||||||
|
}
|
||||||
|
if len(dest) != crypto.BoxPubKeyLen {
|
||||||
|
return nil, errors.New("invalid key length supplied")
|
||||||
|
}
|
||||||
|
var pubKey crypto.BoxPubKey
|
||||||
|
copy(pubKey[:], dest)
|
||||||
|
nodeID := crypto.GetNodeID(&pubKey)
|
||||||
|
nodeMask := &crypto.NodeID{}
|
||||||
|
for i := range nodeMask {
|
||||||
|
nodeMask[i] = 0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Resolving coords")
|
||||||
|
coords, err = n.core.Resolve(nodeID, nodeMask)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("n.core.Resolve: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Found coords:", coords)
|
||||||
|
n.coords.Store(address, coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now know the coords in theory. Let's try dialling the
|
||||||
|
// node again.
|
||||||
|
if session, err = n.tryDial(address, coords); err != nil {
|
||||||
|
return nil, fmt.Errorf("n.tryDial: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Dial OK")
|
|
||||||
go n.listenFromQUIC(session, address)
|
|
||||||
}
|
}
|
||||||
st, err := session.OpenStream()
|
|
||||||
|
if session == nil {
|
||||||
|
return nil, fmt.Errorf("should have found session but didn't")
|
||||||
|
}
|
||||||
|
|
||||||
|
st, err := session.session.OpenStream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.log.Println("session.OpenStream:", err)
|
n.log.Println("session.OpenStream:", err)
|
||||||
|
_ = session.session.CloseWithError(0, "expected to be able to open session")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return QUICStream{st, session}, nil
|
return QUICStream{st, session.session}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) tryDial(address string, coords yggdrasil.Coords) (*session, error) {
|
||||||
|
quicSession, err := quic.Dial(
|
||||||
|
n.core, // yggdrasil.PacketConn
|
||||||
|
coords, // dial address
|
||||||
|
address, // dial SNI
|
||||||
|
n.tlsConfig, // TLS config
|
||||||
|
n.quicConfig, // QUIC config
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(quicSession.ConnectionState().PeerCertificates) != 1 {
|
||||||
|
_ = quicSession.CloseWithError(0, "expected a peer certificate")
|
||||||
|
return nil, errors.New("didn't receive a peer certificate")
|
||||||
|
}
|
||||||
|
if len(quicSession.ConnectionState().PeerCertificates[0].DNSNames) != 1 {
|
||||||
|
_ = quicSession.CloseWithError(0, "expected a DNS name")
|
||||||
|
return nil, errors.New("didn't receive a DNS name")
|
||||||
|
}
|
||||||
|
if gotAddress := quicSession.ConnectionState().PeerCertificates[0].DNSNames[0]; address != gotAddress {
|
||||||
|
_ = quicSession.CloseWithError(0, "you aren't the host I was hoping for")
|
||||||
|
return nil, fmt.Errorf("expected %q but dialled %q", address, gotAddress)
|
||||||
|
}
|
||||||
|
session := n.newSession(quicSession, address)
|
||||||
|
go session.listenFromQUIC()
|
||||||
|
go n.sessionFunc(address)
|
||||||
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) generateTLSConfig() *tls.Config {
|
func (n *Node) generateTLSConfig() *tls.Config {
|
||||||
|
|
|
@ -319,6 +319,11 @@ func (r *FederationSenderInternalAPI) PerformBroadcastEDU(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("r.db.GetAllJoinedHosts: %w", err)
|
return fmt.Errorf("r.db.GetAllJoinedHosts: %w", err)
|
||||||
}
|
}
|
||||||
|
if len(destinations) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.WithContext(ctx).Infof("Sending wake-up EDU to %d destination(s)", len(destinations))
|
||||||
|
|
||||||
edu := &gomatrixserverlib.EDU{
|
edu := &gomatrixserverlib.EDU{
|
||||||
Type: "org.matrix.dendrite.wakeup",
|
Type: "org.matrix.dendrite.wakeup",
|
||||||
|
@ -328,5 +333,13 @@ func (r *FederationSenderInternalAPI) PerformBroadcastEDU(
|
||||||
return fmt.Errorf("r.queues.SendEDU: %w", err)
|
return fmt.Errorf("r.queues.SendEDU: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wakeReq := &api.PerformServersAliveRequest{
|
||||||
|
Servers: destinations,
|
||||||
|
}
|
||||||
|
wakeRes := &api.PerformServersAliveResponse{}
|
||||||
|
if err := r.PerformServersAlive(ctx, wakeReq, wakeRes); err != nil {
|
||||||
|
return fmt.Errorf("r.PerformServersAlive: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -16,7 +16,7 @@ require (
|
||||||
github.com/libp2p/go-libp2p-pubsub v0.2.5
|
github.com/libp2p/go-libp2p-pubsub v0.2.5
|
||||||
github.com/libp2p/go-libp2p-record v0.1.2
|
github.com/libp2p/go-libp2p-record v0.1.2
|
||||||
github.com/libp2p/go-yamux v1.3.7 // indirect
|
github.com/libp2p/go-yamux v1.3.7 // indirect
|
||||||
github.com/lucas-clemente/quic-go v0.17.2
|
github.com/lucas-clemente/quic-go v0.17.3
|
||||||
github.com/matrix-org/dugong v0.0.0-20171220115018-ea0a4690a0d5
|
github.com/matrix-org/dugong v0.0.0-20171220115018-ea0a4690a0d5
|
||||||
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4
|
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3
|
||||||
|
@ -36,9 +36,10 @@ require (
|
||||||
github.com/uber-go/atomic v1.3.0 // indirect
|
github.com/uber-go/atomic v1.3.0 // indirect
|
||||||
github.com/uber/jaeger-client-go v2.15.0+incompatible
|
github.com/uber/jaeger-client-go v2.15.0+incompatible
|
||||||
github.com/uber/jaeger-lib v1.5.0
|
github.com/uber/jaeger-lib v1.5.0
|
||||||
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200715104113-1046b00c3be3
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200806125501-cd4685a3b4de
|
||||||
go.uber.org/atomic v1.4.0
|
go.uber.org/atomic v1.4.0
|
||||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
|
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
|
||||||
|
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de // indirect
|
||||||
gopkg.in/h2non/bimg.v1 v1.0.18
|
gopkg.in/h2non/bimg.v1 v1.0.18
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
)
|
)
|
||||||
|
|
33
go.sum
33
go.sum
|
@ -12,6 +12,7 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv
|
||||||
github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0 h1:p3puK8Sl2xK+2FnnIvY/C0N1aqJo2kbEsdAzU+Tnv48=
|
github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0 h1:p3puK8Sl2xK+2FnnIvY/C0N1aqJo2kbEsdAzU+Tnv48=
|
||||||
github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI=
|
github.com/Arceliar/phony v0.0.0-20191006174943-d0c68492aca0/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
||||||
github.com/Shopify/sarama v1.26.1 h1:3jnfWKD7gVwbB1KSy/lE0szA9duPuSFLViK0o/d3DgA=
|
github.com/Shopify/sarama v1.26.1 h1:3jnfWKD7gVwbB1KSy/lE0szA9duPuSFLViK0o/d3DgA=
|
||||||
github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
|
github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
|
||||||
|
@ -399,8 +400,8 @@ github.com/libp2p/go-yamux v1.3.0 h1:FsYzT16Wq2XqUGJsBbOxoz9g+dFklvNi7jN6YFPfl7U
|
||||||
github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||||
github.com/libp2p/go-yamux v1.3.7 h1:v40A1eSPJDIZwz2AvrV3cxpTZEGDP11QJbukmEhYyQI=
|
github.com/libp2p/go-yamux v1.3.7 h1:v40A1eSPJDIZwz2AvrV3cxpTZEGDP11QJbukmEhYyQI=
|
||||||
github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE=
|
github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE=
|
||||||
github.com/lucas-clemente/quic-go v0.17.2 h1:4iQInIuNQkPNZmsy9rCnwuOzpH0qGnDo4jn0QfI/qE4=
|
github.com/lucas-clemente/quic-go v0.17.3 h1:jMX/MmDNCljfisgMmPGUcBJ+zUh9w3d3ia4YJjYS3TM=
|
||||||
github.com/lucas-clemente/quic-go v0.17.2/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
|
github.com/lucas-clemente/quic-go v0.17.3/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
||||||
github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
|
github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
|
||||||
|
@ -421,16 +422,6 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3 h1:Yb+Wlf
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26 h1:Hr3zjRsq2bhrnp3Ky1qgx/fzCtCALOoGYylh2tpS9K4=
|
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26 h1:Hr3zjRsq2bhrnp3Ky1qgx/fzCtCALOoGYylh2tpS9K4=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0=
|
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200721145051-cea6eafced2b h1:ul/Jc5q5+QBHNvhd9idfglOwyGf/Tc3ittINEbKJPsQ=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200721145051-cea6eafced2b/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200722124340-16fba816840d h1:WZXyd8YI+PQIDYjN8HxtqNRJ1DCckt9wPTi2P8cdnKM=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200722124340-16fba816840d/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200803165250-352235625587 h1:n2IZkm5LI4lACulOa5WU6QwWUhHUtBZez7YIFr1fCOs=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200803165250-352235625587/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200803165739-3bd1ef0f0852 h1:OBvHjLWaT2KS9kGarX2ES0yKBL/wMxAeQB39tRrAAls=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200803165739-3bd1ef0f0852/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804110046-7abbc2918807 h1:ufr+e2FBDuxcO5t/7PMfoiQoma4uyYzS/sLuJSR6tng=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804110046-7abbc2918807/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804124807-5012a626de1d h1:zYk/bQ5bmHDsRqHBl57aBxo5bizsknWU3sunZf9WnWI=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804124807-5012a626de1d h1:zYk/bQ5bmHDsRqHBl57aBxo5bizsknWU3sunZf9WnWI=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804124807-5012a626de1d/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20200804124807-5012a626de1d/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
||||||
github.com/matrix-org/naffka v0.0.0-20200422140631-181f1ee7401f h1:pRz4VTiRCO4zPlEMc3ESdUOcW4PXHH4Kj+YDz1XyE+Y=
|
github.com/matrix-org/naffka v0.0.0-20200422140631-181f1ee7401f h1:pRz4VTiRCO4zPlEMc3ESdUOcW4PXHH4Kj+YDz1XyE+Y=
|
||||||
|
@ -664,6 +655,10 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
|
||||||
github.com/yggdrasil-network/yggdrasil-extras v0.0.0-20200525205615-6c8a4a2e8855/go.mod h1:xQdsh08Io6nV4WRnOVTe6gI8/2iTvfLDQ0CYa5aMt+I=
|
github.com/yggdrasil-network/yggdrasil-extras v0.0.0-20200525205615-6c8a4a2e8855/go.mod h1:xQdsh08Io6nV4WRnOVTe6gI8/2iTvfLDQ0CYa5aMt+I=
|
||||||
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200715104113-1046b00c3be3 h1:teLoIJgPHysREs8P6GlcS/PgaU9W9+GQndikFCQ1lY0=
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200715104113-1046b00c3be3 h1:teLoIJgPHysREs8P6GlcS/PgaU9W9+GQndikFCQ1lY0=
|
||||||
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200715104113-1046b00c3be3/go.mod h1:d+Nz6SPeG6kmeSPFL0cvfWfgwEql75fUnZiAONgvyBE=
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200715104113-1046b00c3be3/go.mod h1:d+Nz6SPeG6kmeSPFL0cvfWfgwEql75fUnZiAONgvyBE=
|
||||||
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200806124633-bd1bdd6be073 h1:Fg4Bszd2qp6eyz/yDMYfB8g2PC1FfNQphGRgZAyD0VU=
|
||||||
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200806124633-bd1bdd6be073/go.mod h1:d+Nz6SPeG6kmeSPFL0cvfWfgwEql75fUnZiAONgvyBE=
|
||||||
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200806125501-cd4685a3b4de h1:p91aw0Mvol825U+5bvV9BBPl+HQxIczj7wxIOxZs70M=
|
||||||
|
github.com/yggdrasil-network/yggdrasil-go v0.3.15-0.20200806125501-cd4685a3b4de/go.mod h1:d+Nz6SPeG6kmeSPFL0cvfWfgwEql75fUnZiAONgvyBE=
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
|
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
|
||||||
|
@ -689,6 +684,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
@ -701,10 +697,19 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
|
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
|
||||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de h1:OVJ6QQUBAesB8CZijKDSsXX7xYVtUhrkY0gwMfbi4p4=
|
||||||
|
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -791,7 +796,11 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69 h1:yBHHx+XZqXJBm6Exke3N7V9gnlsyXxoCPEb1yVenjfk=
|
||||||
|
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
|
Loading…
Reference in New Issue