diff options
author | Neil Alexander <neilalexander@users.noreply.github.com> | 2021-07-15 12:16:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-15 12:16:44 +0100 |
commit | 1827dd7c09baa1bd0ee9ebc51820330416d79bee (patch) | |
tree | f3d2d9dcb7efb1975ca75e48617d0ae2f30e5bd9 /cmd/dendrite-demo-yggdrasil | |
parent | c211fdf5819c836de202e7719ecc924a20781524 (diff) |
Update dendrite-demo-yggdrasil to Yggdrasil 0.4 (#1921)
* Update Yggdrasil P2P demo for Yggdrasil v0.4
* Build fixes
Diffstat (limited to 'cmd/dendrite-demo-yggdrasil')
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/convert/25519.go | 53 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/convert/25519_test.go | 51 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/main.go | 28 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/yggconn/client.go | 1 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/yggconn/node.go | 206 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/yggconn/session.go | 235 | ||||
-rw-r--r-- | cmd/dendrite-demo-yggdrasil/yggconn/stream.go | 20 |
7 files changed, 66 insertions, 528 deletions
diff --git a/cmd/dendrite-demo-yggdrasil/convert/25519.go b/cmd/dendrite-demo-yggdrasil/convert/25519.go deleted file mode 100644 index 97f053ec..00000000 --- a/cmd/dendrite-demo-yggdrasil/convert/25519.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2019 Google LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd -// -// Original code from https://github.com/FiloSottile/age/blob/bbab440e198a4d67ba78591176c7853e62d29e04/internal/age/ssh.go - -package convert - -import ( - "crypto/ed25519" - "crypto/sha512" - "math/big" - - "golang.org/x/crypto/curve25519" -) - -var curve25519P, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10) - -func Ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte { - h := sha512.New() - _, _ = h.Write(pk.Seed()) - out := h.Sum(nil) - return out[:curve25519.ScalarSize] -} - -func Ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte { - // ed25519.PublicKey is a little endian representation of the y-coordinate, - // with the most significant bit set based on the sign of the x-coordinate. - bigEndianY := make([]byte, ed25519.PublicKeySize) - for i, b := range pk { - bigEndianY[ed25519.PublicKeySize-i-1] = b - } - bigEndianY[0] &= 0b0111_1111 - - // The Montgomery u-coordinate is derived through the bilinear map - // u = (1 + y) / (1 - y) - // See https://blog.filippo.io/using-ed25519-keys-for-encryption. - y := new(big.Int).SetBytes(bigEndianY) - denom := big.NewInt(1) - denom.ModInverse(denom.Sub(denom, y), curve25519P) // 1 / (1 - y) - u := y.Mul(y.Add(y, big.NewInt(1)), denom) - u.Mod(u, curve25519P) - - out := make([]byte, curve25519.PointSize) - uBytes := u.Bytes() - for i, b := range uBytes { - out[len(uBytes)-i-1] = b - } - - return out -} diff --git a/cmd/dendrite-demo-yggdrasil/convert/25519_test.go b/cmd/dendrite-demo-yggdrasil/convert/25519_test.go deleted file mode 100644 index 22177b8b..00000000 --- a/cmd/dendrite-demo-yggdrasil/convert/25519_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 The Matrix.org Foundation C.I.C. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package convert - -import ( - "bytes" - "crypto/ed25519" - "encoding/hex" - "testing" - - "golang.org/x/crypto/curve25519" -) - -func TestKeyConversion(t *testing.T) { - edPub, edPriv, err := ed25519.GenerateKey(nil) - if err != nil { - t.Fatal(err) - } - t.Log("Signing public:", hex.EncodeToString(edPub)) - t.Log("Signing private:", hex.EncodeToString(edPriv)) - - cuPriv := Ed25519PrivateKeyToCurve25519(edPriv) - t.Log("Encryption private:", hex.EncodeToString(cuPriv)) - - cuPub := Ed25519PublicKeyToCurve25519(edPub) - t.Log("Converted encryption public:", hex.EncodeToString(cuPub)) - - var realPub, realPriv [32]byte - copy(realPriv[:32], cuPriv[:32]) - curve25519.ScalarBaseMult(&realPub, &realPriv) - t.Log("Scalar-multed encryption public:", hex.EncodeToString(realPub[:])) - - if !bytes.Equal(realPriv[:], cuPriv[:]) { - t.Fatal("Private keys should be equal (this means the test is broken)") - } - if !bytes.Equal(realPub[:], cuPub[:]) { - t.Fatal("Public keys should be equal") - } -} diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go index abeefbe5..95207a60 100644 --- a/cmd/dendrite-demo-yggdrasil/main.go +++ b/cmd/dendrite-demo-yggdrasil/main.go @@ -56,21 +56,23 @@ func main() { flag.Parse() internal.SetupPprof() - ygg, err := yggconn.Setup(*instanceName, ".") + ygg, err := yggconn.Setup(*instanceName, ".", *instancePeer) if err != nil { panic(err) } - ygg.SetMulticastEnabled(true) - if instancePeer != nil && *instancePeer != "" { - if err = ygg.SetStaticPeer(*instancePeer); err != nil { - logrus.WithError(err).Error("Failed to set static peer") + /* + ygg.SetMulticastEnabled(true) + if instancePeer != nil && *instancePeer != "" { + if err = ygg.SetStaticPeer(*instancePeer); err != nil { + logrus.WithError(err).Error("Failed to set static peer") + } } - } + */ cfg := &config.Dendrite{} cfg.Defaults() cfg.Global.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName()) - cfg.Global.PrivateKey = ygg.SigningPrivateKey() + cfg.Global.PrivateKey = ygg.PrivateKey() cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID) cfg.Global.Kafka.UseNaffka = true cfg.UserAPI.AccountDatabase.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-account.db", *instanceName)) @@ -117,18 +119,6 @@ func main() { base, federation, rsAPI, keyRing, true, ) - 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) monolith := setup.Monolith{ diff --git a/cmd/dendrite-demo-yggdrasil/yggconn/client.go b/cmd/dendrite-demo-yggdrasil/yggconn/client.go index 157a9bf2..c7409c21 100644 --- a/cmd/dendrite-demo-yggdrasil/yggconn/client.go +++ b/cmd/dendrite-demo-yggdrasil/yggconn/client.go @@ -51,7 +51,6 @@ func (n *Node) CreateFederationClient( ResponseHeaderTimeout: 10 * time.Second, IdleConnTimeout: 30 * time.Second, DialContext: n.DialerContext, - TLSClientConfig: n.tlsConfig, }, }, ) diff --git a/cmd/dendrite-demo-yggdrasil/yggconn/node.go b/cmd/dendrite-demo-yggdrasil/yggconn/node.go index 9c286dfb..002e8071 100644 --- a/cmd/dendrite-demo-yggdrasil/yggconn/node.go +++ b/cmd/dendrite-demo-yggdrasil/yggconn/node.go @@ -17,7 +17,6 @@ package yggconn import ( "context" "crypto/ed25519" - "crypto/tls" "encoding/hex" "encoding/json" "fmt" @@ -26,60 +25,48 @@ import ( "net" "os" "strings" - "sync" - "time" "github.com/lucas-clemente/quic-go" - "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert" "github.com/matrix-org/gomatrixserverlib" - "go.uber.org/atomic" + "github.com/neilalexander/utp" + ironwoodtypes "github.com/Arceliar/ironwood/types" yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config" + yggdrasilcore "github.com/yggdrasil-network/yggdrasil-go/src/core" + yggdrasildefaults "github.com/yggdrasil-network/yggdrasil-go/src/defaults" yggdrasilmulticast "github.com/yggdrasil-network/yggdrasil-go/src/multicast" - "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" gologme "github.com/gologme/log" ) type Node struct { - core *yggdrasil.Core - config *yggdrasilconfig.NodeConfig - state *yggdrasilconfig.NodeState - multicast *yggdrasilmulticast.Multicast - log *gologme.Logger - listener quic.Listener - tlsConfig *tls.Config - quicConfig *quic.Config - sessions sync.Map // string -> *session - sessionCount atomic.Uint32 - sessionFunc func(address string) - coords sync.Map // string -> yggdrasil.Coords - incoming chan QUICStream - NewSession func(remote gomatrixserverlib.ServerName) + core *yggdrasilcore.Core + config *yggdrasilconfig.NodeConfig + multicast *yggdrasilmulticast.Multicast + log *gologme.Logger + listener quic.Listener + utpSocket *utp.Socket + incoming chan net.Conn } -func (n *Node) Dialer(_, address string) (net.Conn, error) { +func (n *Node) DialerContext(ctx context.Context, _, address string) (net.Conn, error) { tokens := strings.Split(address, ":") raw, err := hex.DecodeString(tokens[0]) if err != nil { return nil, fmt.Errorf("hex.DecodeString: %w", err) } - converted := convert.Ed25519PublicKeyToCurve25519(ed25519.PublicKey(raw)) - convhex := hex.EncodeToString(converted) - return n.Dial("curve25519", convhex) + pk := make(ironwoodtypes.Addr, ed25519.PublicKeySize) + copy(pk, raw[:]) + return n.utpSocket.DialAddrContext(ctx, pk) } -func (n *Node) DialerContext(ctx context.Context, network, address string) (net.Conn, error) { - return n.Dialer(network, address) -} - -func Setup(instanceName, storageDirectory string) (*Node, error) { +func Setup(instanceName, storageDirectory, peerURI string) (*Node, error) { n := &Node{ - core: &yggdrasil.Core{}, - config: yggdrasilconfig.GenerateConfig(), + core: &yggdrasilcore.Core{}, + config: yggdrasildefaults.GenerateConfig(), multicast: &yggdrasilmulticast.Multicast{}, log: gologme.New(os.Stdout, "YGG ", log.Flags()), - incoming: make(chan QUICStream), + incoming: make(chan net.Conn), } yggfile := fmt.Sprintf("%s/%s-yggdrasil.conf", storageDirectory, instanceName) @@ -93,24 +80,11 @@ 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{} + if peerURI != "" { + n.config.Peers = append(n.config.Peers, peerURI) + } n.config.AdminListen = "none" - n.config.MulticastInterfaces = []string{} - n.config.EncryptionPrivateKey = hex.EncodeToString(n.EncryptionPrivateKey()) - n.config.EncryptionPublicKey = hex.EncodeToString(n.EncryptionPublicKey()) j, err := json.MarshalIndent(n.config, "", " ") if err != nil { @@ -123,34 +97,22 @@ func Setup(instanceName, storageDirectory string) (*Node, error) { n.log.EnableLevel("error") n.log.EnableLevel("warn") n.log.EnableLevel("info") - n.state, err = n.core.Start(n.config, n.log) + if err = n.core.Start(n.config, n.log); err != nil { + panic(err) + } + n.utpSocket, err = utp.NewSocketFromPacketConnNoClose(n.core) if err != nil { panic(err) } - if err = n.multicast.Init(n.core, n.state, n.log, nil); err != nil { + if err = n.multicast.Init(n.core, n.config, n.log, nil); err != nil { panic(err) } if err = n.multicast.Start(); err != nil { panic(err) } - n.tlsConfig = n.generateTLSConfig() - n.quicConfig = &quic.Config{ - MaxIncomingStreams: 0, - MaxIncomingUniStreams: 0, - KeepAlive: true, - MaxIdleTimeout: time.Minute * 30, - HandshakeTimeout: time.Second * 15, - } - copy(n.quicConfig.StatelessResetKey, n.EncryptionPublicKey()) - - n.log.Println("Public curve25519:", n.core.EncryptionPublicKey()) - n.log.Println("Public ed25519:", n.core.SigningPublicKey()) - - go func() { - time.Sleep(time.Second) - n.listenFromYgg() - }() + n.log.Println("Public key:", n.core.PublicKey()) + go n.listenFromYgg() return n, nil } @@ -163,64 +125,33 @@ func (n *Node) Stop() { } func (n *Node) DerivedServerName() string { - return hex.EncodeToString(n.SigningPublicKey()) + return hex.EncodeToString(n.PublicKey()) } -func (n *Node) DerivedSessionName() string { - return hex.EncodeToString(n.EncryptionPublicKey()) -} - -func (n *Node) EncryptionPublicKey() []byte { - edkey := n.SigningPublicKey() - return convert.Ed25519PublicKeyToCurve25519(edkey) -} - -func (n *Node) EncryptionPrivateKey() []byte { - edkey := n.SigningPrivateKey() - return convert.Ed25519PrivateKeyToCurve25519(edkey) -} - -func (n *Node) SigningPublicKey() ed25519.PublicKey { - pubBytes, _ := hex.DecodeString(n.config.SigningPublicKey) - return ed25519.PublicKey(pubBytes) -} - -func (n *Node) SigningPrivateKey() ed25519.PrivateKey { - privBytes, _ := hex.DecodeString(n.config.SigningPrivateKey) - return ed25519.PrivateKey(privBytes) +func (n *Node) PrivateKey() ed25519.PrivateKey { + sk := make(ed25519.PrivateKey, ed25519.PrivateKeySize) + sb, err := hex.DecodeString(n.config.PrivateKey) + if err == nil { + copy(sk, sb[:]) + } else { + panic(err) + } + return sk } -func (n *Node) SetSessionFunc(f func(address string)) { - n.sessionFunc = f +func (n *Node) PublicKey() ed25519.PublicKey { + return n.core.PublicKey() } func (n *Node) PeerCount() int { - return len(n.core.GetPeers()) - 1 -} - -func (n *Node) SessionCount() int { - return int(n.sessionCount.Load()) + return len(n.core.GetPeers()) } func (n *Node) KnownNodes() []gomatrixserverlib.ServerName { - nodemap := map[string]struct{}{ - //"b5ae50589e50991dd9dd7d59c5c5f7a4521e8da5b603b7f57076272abc58b374": {}, + nodemap := map[string]struct{}{} + for _, peer := range n.core.GetPeers() { + nodemap[hex.EncodeToString(peer.Key)] = struct{}{} } - for _, peer := range n.core.GetSwitchPeers() { - nodemap[hex.EncodeToString(peer.SigPublicKey[:])] = struct{}{} - } - n.sessions.Range(func(_, v interface{}) bool { - session, ok := v.(quic.Session) - if !ok { - return true - } - if len(session.ConnectionState().PeerCertificates) != 1 { - return true - } - subjectName := session.ConnectionState().PeerCertificates[0].Subject.CommonName - nodemap[subjectName] = struct{}{} - return true - }) var nodes []gomatrixserverlib.ServerName for node := range nodemap { nodes = append(nodes, gomatrixserverlib.ServerName(node)) @@ -229,53 +160,22 @@ func (n *Node) KnownNodes() []gomatrixserverlib.ServerName { } func (n *Node) SetMulticastEnabled(enabled bool) { - if enabled { - n.config.MulticastInterfaces = []string{".*"} - } else { - n.config.MulticastInterfaces = []string{} - } - n.multicast.UpdateConfig(n.config) - if !enabled { - n.DisconnectMulticastPeers() - } + // TODO: There's no dynamic reconfiguration in Yggdrasil v0.4 + // so we need a solution for this. } func (n *Node) DisconnectMulticastPeers() { - for _, sp := range n.core.GetSwitchPeers() { - if !strings.HasPrefix(sp.Endpoint, "fe80") { - continue - } - if err := n.core.DisconnectPeer(sp.Port); err != nil { - n.log.Printf("Failed to disconnect port %d: %s", sp.Port, err) - } - } + // TODO: There's no dynamic reconfiguration in Yggdrasil v0.4 + // so we need a solution for this. } func (n *Node) DisconnectNonMulticastPeers() { - for _, sp := range n.core.GetSwitchPeers() { - if strings.HasPrefix(sp.Endpoint, "fe80") { - continue - } - if err := n.core.DisconnectPeer(sp.Port); err != nil { - n.log.Printf("Failed to disconnect port %d: %s", sp.Port, err) - } - } + // TODO: There's no dynamic reconfiguration in Yggdrasil v0.4 + // so we need a solution for this. } func (n *Node) SetStaticPeer(uri string) error { - n.config.Peers = []string{} - n.core.UpdateConfig(n.config) - n.DisconnectNonMulticastPeers() - if uri != "" { - n.log.Infoln("Adding static peer", uri) - if err := n.core.AddPeer(uri, ""); err != nil { - n.log.Warnln("Adding static peer failed:", err) - return err - } - if err := n.core.CallPeer(uri, ""); err != nil { - n.log.Warnln("Calling static peer failed:", err) - return err - } - } + // TODO: There's no dynamic reconfiguration in Yggdrasil v0.4 + // so we need a solution for this. return nil } diff --git a/cmd/dendrite-demo-yggdrasil/yggconn/session.go b/cmd/dendrite-demo-yggdrasil/yggconn/session.go index 7b56e736..b9a523dd 100644 --- a/cmd/dendrite-demo-yggdrasil/yggconn/session.go +++ b/cmd/dendrite-demo-yggdrasil/yggconn/session.go @@ -16,94 +16,17 @@ package yggconn import ( "context" - "crypto/rand" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "crypto/x509/pkix" - "encoding/hex" - "encoding/pem" - "errors" - "fmt" - "math/big" "net" - "time" - - "github.com/lucas-clemente/quic-go" - "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() { - var err error - n.listener, err = quic.Listen( - n.core, // yggdrasil.PacketConn - n.tlsConfig, // TLS config - n.quicConfig, // QUIC config - ) - if err != nil { - panic(err) - } - for { - n.log.Infoln("Waiting to accept QUIC sessions") - session, err := n.listener.Accept(context.TODO()) + conn, err := n.utpSocket.Accept() if err != nil { - n.log.Println("n.listener.Accept:", err) + n.log.Println("n.utpSocket.Accept:", err) return } - if len(session.ConnectionState().PeerCertificates) != 1 { - _ = session.CloseWithError(0, "expected a peer certificate") - continue - } - address := session.ConnectionState().PeerCertificates[0].DNSNames[0] - n.log.Infoln("Accepted connection from", address) - go n.newSession(session, address).listenFromQUIC() - go n.sessionFunc(address) - } -} - -func (s *session) listenFromQUIC() { - if existing, ok := s.node.sessions.Load(s.address); ok { - 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 { - st, err := s.session.AcceptStream(s.context) - if err != nil { - s.node.log.Println("session.AcceptStream:", err) - return - } - s.node.incoming <- QUICStream{st, s.session} + n.incoming <- conn } } @@ -129,155 +52,5 @@ func (n *Node) Dial(network, address string) (net.Conn, error) { // Implements http.Transport.DialContext func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - s, ok1 := n.sessions.Load(address) - session, ok2 := s.(*session) - if !ok1 || !ok2 { - // First of all, check if we think we know the coords of this - // node. If we do then we'll try to dial to it directly. This - // will either succeed or fail. - if v, ok := n.coords.Load(address); ok { - coords, ok := v.(yggdrasil.Coords) - if !ok { - n.coords.Delete(address) - return nil, errors.New("should have found yggdrasil.Coords but didn't") - } - n.log.Infof("Coords %s for %q cached, trying to dial", coords.String(), address) - var err error - // We think we know the coords. Try to dial the node. - 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) - } - } - - // We either don't know the coords for the node, or we failed - // to dial it before, in which case try to resolve the coords. - if _, ok := n.coords.Load(address); !ok { - var coords yggdrasil.Coords - var err error - - // First look and see if the node is something that we already - // know about from our direct switch peers. - for _, peer := range n.core.GetSwitchPeers() { - if peer.PublicKey.String() == address { - coords = peer.Coords - n.log.Infof("%q is a direct peer, coords are %s", address, coords.String()) - n.coords.Store(address, coords) - break - } - } - - // 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) - } - } - } - - if session == nil { - return nil, fmt.Errorf("should have found session but didn't") - } - - st, err := session.session.OpenStream() - if err != nil { - n.log.Println("session.OpenStream:", err) - _ = session.session.CloseWithError(0, "expected to be able to open session") - return nil, err - } - 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 { - key, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - panic(err) - } - template := x509.Certificate{ - Subject: pkix.Name{ - CommonName: n.DerivedServerName(), - }, - SerialNumber: big.NewInt(1), - NotAfter: time.Now().Add(time.Hour * 24 * 365), - DNSNames: []string{n.DerivedSessionName()}, - } - certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key) - if err != nil { - panic(err) - } - keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) - certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) - - tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) - if err != nil { - panic(err) - } - return &tls.Config{ - Certificates: []tls.Certificate{tlsCert}, - NextProtos: []string{"quic-matrix-ygg"}, - InsecureSkipVerify: true, - ClientAuth: tls.RequireAnyClientCert, - GetClientCertificate: func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) { - return &tlsCert, nil - }, - } + return n.utpSocket.DialContext(ctx, network, address) } diff --git a/cmd/dendrite-demo-yggdrasil/yggconn/stream.go b/cmd/dendrite-demo-yggdrasil/yggconn/stream.go deleted file mode 100644 index dac7447e..00000000 --- a/cmd/dendrite-demo-yggdrasil/yggconn/stream.go +++ /dev/null @@ -1,20 +0,0 @@ -package yggconn - -import ( - "net" - - "github.com/lucas-clemente/quic-go" -) - -type QUICStream struct { - quic.Stream - session quic.Session -} - -func (s QUICStream) LocalAddr() net.Addr { - return s.session.LocalAddr() -} - -func (s QUICStream) RemoteAddr() net.Addr { - return s.session.RemoteAddr() -} |