aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/gobind-pinecone/build.sh13
-rw-r--r--build/gobind-pinecone/monolith.go418
-rw-r--r--build/gobind-pinecone/platform_ios.go (renamed from build/gobind/platform_ios.go)0
-rw-r--r--build/gobind-pinecone/platform_other.go (renamed from build/gobind/platform_other.go)0
-rw-r--r--build/gobind-yggdrasil/build.sh25
-rw-r--r--build/gobind-yggdrasil/monolith.go (renamed from build/gobind/monolith.go)0
-rw-r--r--build/gobind-yggdrasil/platform_ios.go25
-rw-r--r--build/gobind-yggdrasil/platform_other.go12
-rw-r--r--build/gobind/build.sh6
-rw-r--r--cmd/dendrite-demo-pinecone/conn/client.go91
-rw-r--r--cmd/dendrite-demo-pinecone/conn/ws.go81
-rw-r--r--cmd/dendrite-demo-pinecone/embed/embed_other.go9
-rw-r--r--cmd/dendrite-demo-pinecone/embed/embed_riotweb.go83
-rw-r--r--cmd/dendrite-demo-pinecone/main.go279
-rw-r--r--cmd/dendrite-demo-pinecone/rooms/rooms.go150
-rw-r--r--cmd/dendrite-demo-yggdrasil/README.md2
-rw-r--r--docs/INSTALL.md2
-rw-r--r--go.mod7
-rw-r--r--go.sum86
19 files changed, 1264 insertions, 25 deletions
diff --git a/build/gobind-pinecone/build.sh b/build/gobind-pinecone/build.sh
new file mode 100644
index 00000000..6fd05a64
--- /dev/null
+++ b/build/gobind-pinecone/build.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+TARGET=""
+
+while getopts "ai" option
+do
+ case "$option"
+ in
+ a) gomobile bind -v -target android -trimpath -ldflags="-s -w" github.com/matrix-org/dendrite/build/gobind-pinecone ;;
+ i) gomobile bind -v -target ios -trimpath -ldflags="-s -w" github.com/matrix-org/dendrite/build/gobind-pinecone ;;
+ *) echo "No target specified, specify -a or -i"; exit 1 ;;
+ esac
+done \ No newline at end of file
diff --git a/build/gobind-pinecone/monolith.go b/build/gobind-pinecone/monolith.go
new file mode 100644
index 00000000..b5e1593a
--- /dev/null
+++ b/build/gobind-pinecone/monolith.go
@@ -0,0 +1,418 @@
+package gobind
+
+import (
+ "context"
+ "crypto/ed25519"
+ "crypto/rand"
+ "crypto/tls"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math"
+ "net"
+ "net/http"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/gorilla/mux"
+ "github.com/matrix-org/dendrite/appservice"
+ "github.com/matrix-org/dendrite/clientapi/userutil"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/conn"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/rooms"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
+ "github.com/matrix-org/dendrite/eduserver"
+ "github.com/matrix-org/dendrite/eduserver/cache"
+ "github.com/matrix-org/dendrite/federationsender"
+ "github.com/matrix-org/dendrite/federationsender/api"
+ "github.com/matrix-org/dendrite/internal/httputil"
+ "github.com/matrix-org/dendrite/keyserver"
+ "github.com/matrix-org/dendrite/roomserver"
+ "github.com/matrix-org/dendrite/setup"
+ "github.com/matrix-org/dendrite/setup/config"
+ "github.com/matrix-org/dendrite/setup/process"
+ "github.com/matrix-org/dendrite/userapi"
+ userapiAPI "github.com/matrix-org/dendrite/userapi/api"
+ "github.com/matrix-org/gomatrixserverlib"
+ "github.com/sirupsen/logrus"
+ "go.uber.org/atomic"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/h2c"
+
+ pineconeMulticast "github.com/matrix-org/pinecone/multicast"
+ pineconeRouter "github.com/matrix-org/pinecone/router"
+ pineconeSessions "github.com/matrix-org/pinecone/sessions"
+ "github.com/matrix-org/pinecone/types"
+ pineconeTypes "github.com/matrix-org/pinecone/types"
+)
+
+const (
+ PeerTypeRemote = pineconeRouter.PeerTypeRemote
+ PeerTypeMulticast = pineconeRouter.PeerTypeMulticast
+ PeerTypeBluetooth = pineconeRouter.PeerTypeBluetooth
+)
+
+type DendriteMonolith struct {
+ logger logrus.Logger
+ PineconeRouter *pineconeRouter.Router
+ PineconeMulticast *pineconeMulticast.Multicast
+ PineconeQUIC *pineconeSessions.Sessions
+ StorageDirectory string
+ CacheDirectory string
+ staticPeerURI string
+ staticPeerMutex sync.RWMutex
+ staticPeerAttempts atomic.Uint32
+ listener net.Listener
+ httpServer *http.Server
+ processContext *process.ProcessContext
+ userAPI userapiAPI.UserInternalAPI
+}
+
+func (m *DendriteMonolith) BaseURL() string {
+ return fmt.Sprintf("http://%s", m.listener.Addr().String())
+}
+
+func (m *DendriteMonolith) PeerCount(peertype int) int {
+ return m.PineconeRouter.PeerCount(peertype)
+}
+
+func (m *DendriteMonolith) SessionCount() int {
+ return len(m.PineconeQUIC.Sessions())
+}
+
+func (m *DendriteMonolith) SetMulticastEnabled(enabled bool) {
+ if enabled {
+ m.PineconeMulticast.Start()
+ } else {
+ m.PineconeMulticast.Stop()
+ m.DisconnectType(pineconeRouter.PeerTypeMulticast)
+ }
+}
+
+func (m *DendriteMonolith) SetStaticPeer(uri string) {
+ m.staticPeerMutex.Lock()
+ m.staticPeerURI = uri
+ m.staticPeerMutex.Unlock()
+ m.DisconnectType(pineconeRouter.PeerTypeRemote)
+ if uri != "" {
+ m.staticPeerConnect()
+ }
+}
+
+func (m *DendriteMonolith) DisconnectType(peertype int) {
+ for _, p := range m.PineconeRouter.Peers() {
+ if peertype == p.PeerType {
+ _ = m.PineconeRouter.Disconnect(types.SwitchPortID(p.Port), nil)
+ }
+ }
+}
+
+func (m *DendriteMonolith) DisconnectZone(zone string) {
+ for _, p := range m.PineconeRouter.Peers() {
+ if zone == p.Zone {
+ _ = m.PineconeRouter.Disconnect(types.SwitchPortID(p.Port), nil)
+ }
+ }
+}
+
+func (m *DendriteMonolith) DisconnectPort(port int) error {
+ return m.PineconeRouter.Disconnect(types.SwitchPortID(port), nil)
+}
+
+func (m *DendriteMonolith) Conduit(zone string, peertype int) (*Conduit, error) {
+ l, r := net.Pipe()
+ conduit := &Conduit{conn: r, port: 0}
+ go func() {
+ conduit.portMutex.Lock()
+ defer conduit.portMutex.Unlock()
+ loop:
+ for i := 1; i <= 10; i++ {
+ logrus.Errorf("Attempting authenticated connect (attempt %d)", i)
+ var err error
+ conduit.port, err = m.PineconeRouter.AuthenticatedConnect(l, zone, peertype)
+ switch err {
+ case io.ErrClosedPipe:
+ logrus.Errorf("Authenticated connect failed due to closed pipe (attempt %d)", i)
+ return
+ case io.EOF:
+ logrus.Errorf("Authenticated connect failed due to EOF (attempt %d)", i)
+ break loop
+ case nil:
+ logrus.Errorf("Authenticated connect succeeded, connected to port %d (attempt %d)", conduit.port, i)
+ return
+ default:
+ logrus.WithError(err).Errorf("Authenticated connect failed (attempt %d)", i)
+ time.Sleep(time.Second)
+ }
+ }
+ _ = l.Close()
+ _ = r.Close()
+ }()
+ return conduit, nil
+}
+
+func (m *DendriteMonolith) RegisterUser(localpart, password string) (string, error) {
+ pubkey := m.PineconeRouter.PublicKey()
+ userID := userutil.MakeUserID(
+ localpart,
+ gomatrixserverlib.ServerName(hex.EncodeToString(pubkey[:])),
+ )
+ userReq := &userapiAPI.PerformAccountCreationRequest{
+ AccountType: userapiAPI.AccountTypeUser,
+ Localpart: localpart,
+ Password: password,
+ }
+ userRes := &userapiAPI.PerformAccountCreationResponse{}
+ if err := m.userAPI.PerformAccountCreation(context.Background(), userReq, userRes); err != nil {
+ return userID, fmt.Errorf("userAPI.PerformAccountCreation: %w", err)
+ }
+ return userID, nil
+}
+
+func (m *DendriteMonolith) RegisterDevice(localpart, deviceID string) (string, error) {
+ accessTokenBytes := make([]byte, 16)
+ n, err := rand.Read(accessTokenBytes)
+ if err != nil {
+ return "", fmt.Errorf("rand.Read: %w", err)
+ }
+ loginReq := &userapiAPI.PerformDeviceCreationRequest{
+ Localpart: localpart,
+ DeviceID: &deviceID,
+ AccessToken: hex.EncodeToString(accessTokenBytes[:n]),
+ }
+ loginRes := &userapiAPI.PerformDeviceCreationResponse{}
+ if err := m.userAPI.PerformDeviceCreation(context.Background(), loginReq, loginRes); err != nil {
+ return "", fmt.Errorf("userAPI.PerformDeviceCreation: %w", err)
+ }
+ if !loginRes.DeviceCreated {
+ return "", fmt.Errorf("device was not created")
+ }
+ return loginRes.Device.AccessToken, nil
+}
+
+func (m *DendriteMonolith) staticPeerConnect() {
+ m.staticPeerMutex.RLock()
+ uri := m.staticPeerURI
+ m.staticPeerMutex.RUnlock()
+ if uri == "" {
+ return
+ }
+ if err := conn.ConnectToPeer(m.PineconeRouter, uri); err != nil {
+ exp := time.Second * time.Duration(math.Exp2(float64(m.staticPeerAttempts.Inc())))
+ time.AfterFunc(exp, m.staticPeerConnect)
+ } else {
+ m.staticPeerAttempts.Store(0)
+ }
+}
+
+// nolint:gocyclo
+func (m *DendriteMonolith) Start() {
+ var err error
+ var sk ed25519.PrivateKey
+ var pk ed25519.PublicKey
+ keyfile := fmt.Sprintf("%s/p2p.key", m.StorageDirectory)
+ if _, err = os.Stat(keyfile); os.IsNotExist(err) {
+ if pk, sk, err = ed25519.GenerateKey(nil); err != nil {
+ panic(err)
+ }
+ if err = ioutil.WriteFile(keyfile, sk, 0644); err != nil {
+ panic(err)
+ }
+ } else if err == nil {
+ if sk, err = ioutil.ReadFile(keyfile); err != nil {
+ panic(err)
+ }
+ if len(sk) != ed25519.PrivateKeySize {
+ panic("the private key is not long enough")
+ }
+ pk = sk.Public().(ed25519.PublicKey)
+ }
+
+ m.listener, err = net.Listen("tcp", "localhost:65432")
+ if err != nil {
+ panic(err)
+ }
+
+ m.logger = logrus.Logger{
+ Out: BindLogger{},
+ }
+ m.logger.SetOutput(BindLogger{})
+ logrus.SetOutput(BindLogger{})
+
+ logger := log.New(os.Stdout, "PINECONE: ", 0)
+ m.PineconeRouter = pineconeRouter.NewRouter(logger, "dendrite", sk, pk, nil)
+ m.PineconeQUIC = pineconeSessions.NewSessions(logger, m.PineconeRouter)
+ m.PineconeMulticast = pineconeMulticast.NewMulticast(logger, m.PineconeRouter)
+
+ m.PineconeRouter.SetDisconnectedCallback(func(port pineconeTypes.SwitchPortID, public pineconeTypes.PublicKey, peertype int, err error) {
+ if peertype == pineconeRouter.PeerTypeRemote {
+ m.staticPeerAttempts.Store(0)
+ time.AfterFunc(time.Second, m.staticPeerConnect)
+ }
+ })
+
+ prefix := hex.EncodeToString(pk)
+ cfg := &config.Dendrite{}
+ cfg.Defaults()
+ cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
+ cfg.Global.PrivateKey = sk
+ cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
+ cfg.Global.Kafka.UseNaffka = true
+ cfg.Global.Kafka.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-naffka.db", m.StorageDirectory, prefix))
+ cfg.UserAPI.AccountDatabase.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-account.db", m.StorageDirectory, prefix))
+ cfg.UserAPI.DeviceDatabase.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-device.db", m.StorageDirectory, prefix))
+ cfg.MediaAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-mediaapi.db", m.CacheDirectory, prefix))
+ cfg.SyncAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-syncapi.db", m.StorageDirectory, prefix))
+ cfg.RoomServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-roomserver.db", m.StorageDirectory, prefix))
+ cfg.SigningKeyServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-signingkeyserver.db", m.StorageDirectory, prefix))
+ cfg.KeyServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-keyserver.db", m.StorageDirectory, prefix))
+ cfg.FederationSender.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-federationsender.db", m.StorageDirectory, prefix))
+ cfg.AppServiceAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s/%s-appservice.db", m.StorageDirectory, prefix))
+ cfg.MediaAPI.BasePath = config.Path(fmt.Sprintf("%s/media", m.CacheDirectory))
+ cfg.MediaAPI.AbsBasePath = config.Path(fmt.Sprintf("%s/media", m.CacheDirectory))
+ if err := cfg.Derive(); err != nil {
+ panic(err)
+ }
+
+ base := setup.NewBaseDendrite(cfg, "Monolith", false)
+ defer base.Close() // nolint: errcheck
+
+ accountDB := base.CreateAccountsDB()
+ federation := conn.CreateFederationClient(base, m.PineconeQUIC)
+
+ serverKeyAPI := &signing.YggdrasilKeys{}
+ keyRing := serverKeyAPI.KeyRing()
+
+ rsAPI := roomserver.NewInternalAPI(
+ base, keyRing,
+ )
+
+ fsAPI := federationsender.NewInternalAPI(
+ base, federation, rsAPI, keyRing,
+ )
+
+ keyAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, fsAPI)
+ m.userAPI = userapi.NewInternalAPI(accountDB, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI)
+ keyAPI.SetUserAPI(m.userAPI)
+
+ eduInputAPI := eduserver.NewInternalAPI(
+ base, cache.New(), m.userAPI,
+ )
+
+ asAPI := appservice.NewInternalAPI(base, m.userAPI, rsAPI)
+
+ // 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
+ rsAPI.SetFederationSenderAPI(fsAPI)
+
+ monolith := setup.Monolith{
+ Config: base.Cfg,
+ AccountDB: accountDB,
+ Client: conn.CreateClient(base, m.PineconeQUIC),
+ FedClient: federation,
+ KeyRing: keyRing,
+
+ AppserviceAPI: asAPI,
+ EDUInternalAPI: eduInputAPI,
+ FederationSenderAPI: fsAPI,
+ RoomserverAPI: rsAPI,
+ UserAPI: m.userAPI,
+ KeyAPI: keyAPI,
+ ExtPublicRoomsProvider: rooms.NewPineconeRoomProvider(m.PineconeRouter, m.PineconeQUIC, fsAPI, federation),
+ }
+ monolith.AddAllPublicRoutes(
+ base.ProcessContext,
+ base.PublicClientAPIMux,
+ base.PublicFederationAPIMux,
+ base.PublicKeyAPIMux,
+ base.PublicMediaAPIMux,
+ )
+
+ httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
+ httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
+ httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
+ httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
+
+ pMux := mux.NewRouter().SkipClean(true).UseEncodedPath()
+ pMux.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.PublicFederationAPIMux)
+ pMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
+
+ pHTTP := m.PineconeQUIC.HTTP()
+ pHTTP.Mux().Handle(httputil.PublicFederationPathPrefix, pMux)
+ pHTTP.Mux().Handle(httputil.PublicMediaPathPrefix, pMux)
+
+ // Build both ends of a HTTP multiplex.
+ h2s := &http2.Server{}
+ m.httpServer = &http.Server{
+ Addr: ":0",
+ TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
+ ReadTimeout: 10 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ IdleTimeout: 30 * time.Second,
+ BaseContext: func(_ net.Listener) context.Context {
+ return context.Background()
+ },
+ Handler: h2c.NewHandler(pMux, h2s),
+ }
+ m.processContext = base.ProcessContext
+
+ go func() {
+ m.logger.Info("Listening on ", cfg.Global.ServerName)
+ m.logger.Fatal(m.httpServer.Serve(m.PineconeQUIC))
+ }()
+ go func() {
+ logrus.Info("Listening on ", m.listener.Addr())
+ logrus.Fatal(http.Serve(m.listener, httpRouter))
+ }()
+ go func() {
+ logrus.Info("Sending wake-up message to known nodes")
+ req := &api.PerformBroadcastEDURequest{}
+ res := &api.PerformBroadcastEDUResponse{}
+ if err := fsAPI.PerformBroadcastEDU(context.TODO(), req, res); err != nil {
+ logrus.WithError(err).Error("Failed to send wake-up message to known nodes")
+ }
+ }()
+}
+
+func (m *DendriteMonolith) Stop() {
+ _ = m.listener.Close()
+ m.PineconeMulticast.Stop()
+ _ = m.PineconeQUIC.Close()
+ m.processContext.ShutdownDendrite()
+ _ = m.PineconeRouter.Close()
+}
+
+type Conduit struct {
+ conn net.Conn
+ port types.SwitchPortID
+ portMutex sync.Mutex
+}
+
+func (c *Conduit) Port() int {
+ c.portMutex.Lock()
+ defer c.portMutex.Unlock()
+ return int(c.port)
+}
+
+func (c *Conduit) Read(b []byte) (int, error) {
+ return c.conn.Read(b)
+}
+
+func (c *Conduit) ReadCopy() ([]byte, error) {
+ var buf [65535 * 2]byte
+ n, err := c.conn.Read(buf[:])
+ if err != nil {
+ return nil, err
+ }
+ return buf[:n], nil
+}
+
+func (c *Conduit) Write(b []byte) (int, error) {
+ return c.conn.Write(b)
+}
+
+func (c *Conduit) Close() error {
+ return c.conn.Close()
+}
diff --git a/build/gobind/platform_ios.go b/build/gobind-pinecone/platform_ios.go
index 01f8a6a0..01f8a6a0 100644
--- a/build/gobind/platform_ios.go
+++ b/build/gobind-pinecone/platform_ios.go
diff --git a/build/gobind/platform_other.go b/build/gobind-pinecone/platform_other.go
index fdfb13bc..fdfb13bc 100644
--- a/build/gobind/platform_other.go
+++ b/build/gobind-pinecone/platform_other.go
diff --git a/build/gobind-yggdrasil/build.sh b/build/gobind-yggdrasil/build.sh
new file mode 100644
index 00000000..a9889d8d
--- /dev/null
+++ b/build/gobind-yggdrasil/build.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+#!/bin/sh
+
+TARGET=""
+
+while getopts "ai" option
+do
+ case "$option"
+ in
+ a) TARGET="android";;
+ i) TARGET="ios";;
+ esac
+done
+
+if [[ $TARGET = "" ]];
+then
+ echo "No target specified, specify -a or -i"
+ exit 1
+fi
+
+gomobile bind -v \
+ -target $TARGET \
+ -ldflags "-X github.com/yggdrasil-network/yggdrasil-go/src/version.buildName=dendrite" \
+ github.com/matrix-org/dendrite/build/gobind-pinecone \ No newline at end of file
diff --git a/build/gobind/monolith.go b/build/gobind-yggdrasil/monolith.go
index 332d156b..332d156b 100644
--- a/build/gobind/monolith.go
+++ b/build/gobind-yggdrasil/monolith.go
diff --git a/build/gobind-yggdrasil/platform_ios.go b/build/gobind-yggdrasil/platform_ios.go
new file mode 100644
index 00000000..01f8a6a0
--- /dev/null
+++ b/build/gobind-yggdrasil/platform_ios.go
@@ -0,0 +1,25 @@
+// +build ios
+
+package gobind
+
+/*
+#cgo CFLAGS: -x objective-c
+#cgo LDFLAGS: -framework Foundation
+#import <Foundation/Foundation.h>
+void Log(const char *text) {
+ NSString *nss = [NSString stringWithUTF8String:text];
+ NSLog(@"%@", nss);
+}
+*/
+import "C"
+import "unsafe"
+
+type BindLogger struct {
+}
+
+func (nsl BindLogger) Write(p []byte) (n int, err error) {
+ p = append(p, 0)
+ cstr := (*C.char)(unsafe.Pointer(&p[0]))
+ C.Log(cstr)
+ return len(p), nil
+}
diff --git a/build/gobind-yggdrasil/platform_other.go b/build/gobind-yggdrasil/platform_other.go
new file mode 100644
index 00000000..fdfb13bc
--- /dev/null
+++ b/build/gobind-yggdrasil/platform_other.go
@@ -0,0 +1,12 @@
+// +build !ios
+
+package gobind
+
+import "log"
+
+type BindLogger struct{}
+
+func (nsl BindLogger) Write(p []byte) (n int, err error) {
+ log.Println(string(p))
+ return len(p), nil
+}
diff --git a/build/gobind/build.sh b/build/gobind/build.sh
deleted file mode 100644
index aa2cdfc5..00000000
--- a/build/gobind/build.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-gomobile bind -v \
- -ldflags "-X github.com/yggdrasil-network/yggdrasil-go/src/version.buildName=dendrite" \
- -target ios \
- github.com/matrix-org/dendrite/build/gobind \ No newline at end of file
diff --git a/cmd/dendrite-demo-pinecone/conn/client.go b/cmd/dendrite-demo-pinecone/conn/client.go
new file mode 100644
index 00000000..bf23085d
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/conn/client.go
@@ -0,0 +1,91 @@
+package conn
+
+import (
+ "fmt"
+ "net"
+ "net/http"
+ "strings"
+
+ "github.com/gorilla/websocket"
+ "github.com/matrix-org/dendrite/setup"
+ "github.com/matrix-org/gomatrixserverlib"
+
+ pineconeRouter "github.com/matrix-org/pinecone/router"
+ pineconeSessions "github.com/matrix-org/pinecone/sessions"
+)
+
+func ConnectToPeer(pRouter *pineconeRouter.Router, peer string) error {
+ var parent net.Conn
+ if strings.HasPrefix(peer, "ws://") || strings.HasPrefix(peer, "wss://") {
+ c, _, err := websocket.DefaultDialer.Dial(peer, nil)
+ if err != nil {
+ return fmt.Errorf("websocket.DefaultDialer.Dial: %w", err)
+ }
+ parent = WrapWebSocketConn(c)
+ } else {
+ var err error
+ parent, err = net.Dial("tcp", peer)
+ if err != nil {
+ return fmt.Errorf("net.Dial: %w", err)
+ }
+ }
+ if parent == nil {
+ return fmt.Errorf("failed to wrap connection")
+ }
+ _, err := pRouter.AuthenticatedConnect(parent, "static", pineconeRouter.PeerTypeRemote)
+ return err
+}
+
+type RoundTripper struct {
+ inner *http.Transport
+}
+
+func (y *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ req.URL.Scheme = "http"
+ return y.inner.RoundTrip(req)
+}
+
+func CreateClient(
+ base *setup.BaseDendrite, s *pineconeSessions.Sessions,
+) *gomatrixserverlib.Client {
+ tr := &http.Transport{}
+ tr.RegisterProtocol(
+ "matrix", &RoundTripper{
+ inner: &http.Transport{
+ MaxIdleConns: 100,
+ MaxIdleConnsPerHost: 5,
+ Dial: s.Dial,
+ DialContext: s.DialContext,
+ DialTLS: s.DialTLS,
+ DialTLSContext: s.DialTLSContext,
+ },
+ },
+ )
+ return gomatrixserverlib.NewClient(
+ gomatrixserverlib.WithTransport(tr),
+ )
+}
+
+func CreateFederationClient(
+ base *setup.BaseDendrite, s *pineconeSessions.Sessions,
+) *gomatrixserverlib.FederationClient {
+ tr := &http.Transport{}
+ tr.RegisterProtocol(
+ "matrix", &RoundTripper{
+ inner: &http.Transport{
+ MaxIdleConns: 100,
+ MaxIdleConnsPerHost: 5,
+ Dial: s.Dial,
+ DialContext: s.DialContext,
+ DialTLS: s.DialTLS,
+ DialTLSContext: s.DialTLSContext,
+ },
+ },
+ )
+ return gomatrixserverlib.NewFederationClient(
+ base.Cfg.Global.ServerName,
+ base.Cfg.Global.KeyID,
+ base.Cfg.Global.PrivateKey,
+ gomatrixserverlib.WithTransport(tr),
+ )
+}
diff --git a/cmd/dendrite-demo-pinecone/conn/ws.go b/cmd/dendrite-demo-pinecone/conn/ws.go
new file mode 100644
index 00000000..ef403e29
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/conn/ws.go
@@ -0,0 +1,81 @@
+package conn
+
+import (
+ "io"
+ "net"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+func WrapWebSocketConn(c *websocket.Conn) *WebSocketConn {
+ return &WebSocketConn{c: c}
+}
+
+type WebSocketConn struct {
+ r io.Reader
+ c *websocket.Conn
+}
+
+func (c *WebSocketConn) Write(p []byte) (int, error) {
+ err := c.c.WriteMessage(websocket.BinaryMessage, p)
+ if err != nil {
+ return 0, err
+ }
+ return len(p), nil
+}
+
+func (c *WebSocketConn) Read(p []byte) (int, error) {
+ for {
+ if c.r == nil {
+ // Advance to next message.
+ var err error
+ _, c.r, err = c.c.NextReader()
+ if err != nil {
+ return 0, err
+ }
+ }
+ n, err := c.r.Read(p)
+ if err == io.EOF {
+ // At end of message.
+ c.r = nil
+ if n > 0 {
+ return n, nil
+ } else {
+ // No data read, continue to next message.
+ continue
+ }
+ }
+ return n, err
+ }
+}
+
+func (c *WebSocketConn) Close() error {
+ return c.c.Close()
+}
+
+func (c *WebSocketConn) LocalAddr() net.Addr {
+ return c.c.LocalAddr()
+}
+
+func (c *WebSocketConn) RemoteAddr() net.Addr {
+ return c.c.RemoteAddr()
+}
+
+func (c *WebSocketConn) SetDeadline(t time.Time) error {
+ if err := c.SetReadDeadline(t); err != nil {
+ return err
+ }
+ if err := c.SetWriteDeadline(t); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (c *WebSocketConn) SetReadDeadline(t time.Time) error {
+ return c.c.SetReadDeadline(t)
+}
+
+func (c *WebSocketConn) SetWriteDeadline(t time.Time) error {
+ return c.c.SetWriteDeadline(t)
+}
diff --git a/cmd/dendrite-demo-pinecone/embed/embed_other.go b/cmd/dendrite-demo-pinecone/embed/embed_other.go
new file mode 100644
index 00000000..59888114
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/embed/embed_other.go
@@ -0,0 +1,9 @@
+// +build !riotweb
+
+package embed
+
+import "github.com/gorilla/mux"
+
+func Embed(_ *mux.Router, _ int, _ string) {
+
+}
diff --git a/cmd/dendrite-demo-pinecone/embed/embed_riotweb.go b/cmd/dendrite-demo-pinecone/embed/embed_riotweb.go
new file mode 100644
index 00000000..d25745ca
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/embed/embed_riotweb.go
@@ -0,0 +1,83 @@
+// +build riotweb
+
+package embed
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "regexp"
+
+ "github.com/gorilla/mux"
+ "github.com/tidwall/sjson"
+)
+
+// From within the Riot Web directory:
+// go run github.com/mjibson/esc -o /path/to/dendrite/internal/embed/fs_riotweb.go -private -pkg embed .
+
+var cssFile = regexp.MustCompile("\\.css$")
+var jsFile = regexp.MustCompile("\\.js$")
+
+type mimeFixingHandler struct {
+ fs http.Handler
+}
+
+func (h mimeFixingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ ruri := r.RequestURI
+ fmt.Println(ruri)
+ switch {
+ case cssFile.MatchString(ruri):
+ w.Header().Set("Content-Type", "text/css")
+ case jsFile.MatchString(ruri):
+ w.Header().Set("Content-Type", "application/javascript")
+ default:
+ }
+ h.fs.ServeHTTP(w, r)
+}
+
+func Embed(rootMux *mux.Router, listenPort int, serverName string) {
+ embeddedFS := _escFS(false)
+ embeddedServ := mimeFixingHandler{http.FileServer(embeddedFS)}
+
+ rootMux.NotFoundHandler = embeddedServ
+ rootMux.HandleFunc("/config.json", func(w http.ResponseWriter, r *http.Request) {
+ url := fmt.Sprintf("http://%s:%d", r.Header("Host"), listenPort)
+ configFile, err := embeddedFS.Open("/config.sample.json")
+ if err != nil {
+ w.WriteHeader(500)
+ io.WriteString(w, "Couldn't open the file: "+err.Error())
+ return
+ }
+ configFileInfo, err := configFile.Stat()
+ if err != nil {
+ w.WriteHeader(500)
+ io.WriteString(w, "Couldn't stat the file: "+err.Error())
+ return
+ }
+ buf := make([]byte, configFileInfo.Size())
+ n, err := configFile.Read(buf)
+ if err != nil {
+ w.WriteHeader(500)
+ io.WriteString(w, "Couldn't read the file: "+err.Error())
+ return
+ }
+ if int64(n) != configFileInfo.Size() {
+ w.WriteHeader(500)
+ io.WriteString(w, "The returned file size didn't match what we expected")
+ return
+ }
+ js, _ := sjson.SetBytes(buf, "default_server_config.m\\.homeserver.base_url", url)
+ js, _ = sjson.SetBytes(js, "default_server_config.m\\.homeserver.server_name", serverName)
+ js, _ = sjson.SetBytes(js, "brand", fmt.Sprintf("Riot %s", serverName))
+ js, _ = sjson.SetBytes(js, "disable_guests", true)
+ js, _ = sjson.SetBytes(js, "disable_3pid_login", true)
+ js, _ = sjson.DeleteBytes(js, "welcomeUserId")
+ _, _ = w.Write(js)
+ })
+
+ fmt.Println("*-------------------------------*")
+ fmt.Println("| This build includes Riot Web! |")
+ fmt.Println("*-------------------------------*")
+ fmt.Println("Point your browser to:", url)
+ fmt.Println()
+}
diff --git a/cmd/dendrite-demo-pinecone/main.go b/cmd/dendrite-demo-pinecone/main.go
new file mode 100644
index 00000000..46a533f0
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/main.go
@@ -0,0 +1,279 @@
+// 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 main
+
+import (
+ "context"
+ "crypto/ed25519"
+ "crypto/tls"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math"
+ "net"
+ "net/http"
+ "os"
+ "time"
+
+ "github.com/gorilla/mux"
+ "github.com/gorilla/websocket"
+ "github.com/matrix-org/dendrite/appservice"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/conn"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/embed"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/rooms"
+ "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
+ "github.com/matrix-org/dendrite/eduserver"
+ "github.com/matrix-org/dendrite/eduserver/cache"
+ "github.com/matrix-org/dendrite/federationsender"
+ "github.com/matrix-org/dendrite/federationsender/api"
+ "github.com/matrix-org/dendrite/internal"
+ "github.com/matrix-org/dendrite/internal/httputil"
+ "github.com/matrix-org/dendrite/keyserver"
+ "github.com/matrix-org/dendrite/roomserver"
+ "github.com/matrix-org/dendrite/setup"
+ "github.com/matrix-org/dendrite/setup/config"
+ "github.com/matrix-org/dendrite/userapi"
+ "github.com/matrix-org/gomatrixserverlib"
+ "go.uber.org/atomic"
+
+ pineconeMulticast "github.com/matrix-org/pinecone/multicast"
+ pineconeRouter "github.com/matrix-org/pinecone/router"
+ pineconeSessions "github.com/matrix-org/pinecone/sessions"
+ pineconeTypes "github.com/matrix-org/pinecone/types"
+
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ instanceName = flag.String("name", "dendrite-p2p-pinecone", "the name of this P2P demo instance")
+ instancePort = flag.Int("port", 8008, "the port that the client API will listen on")
+ instancePeer = flag.String("peer", "", "the static Pinecone peer to connect to")
+ instanceListen = flag.String("listen", ":0", "the port Pinecone peers can connect to")
+)
+
+// nolint:gocyclo
+func main() {
+ flag.Parse()
+ internal.SetupPprof()
+
+ var pk ed25519.PublicKey
+ var sk ed25519.PrivateKey
+
+ keyfile := *instanceName + ".key"
+ if _, err := os.Stat(keyfile); os.IsNotExist(err) {
+ if pk, sk, err = ed25519.GenerateKey(nil); err != nil {
+ panic(err)
+ }
+ if err = ioutil.WriteFile(keyfile, sk, 0644); err != nil {
+ panic(err)
+ }
+ } else if err == nil {
+ if sk, err = ioutil.ReadFile(keyfile); err != nil {
+ panic(err)
+ }
+ if len(sk) != ed25519.PrivateKeySize {
+ panic("the private key is not long enough")
+ }
+ pk = sk.Public().(ed25519.PublicKey)
+ }
+
+ logger := log.New(os.Stdout, "", 0)
+ pRouter := pineconeRouter.NewRouter(logger, "dendrite", sk, pk, nil)
+
+ go func() {
+ listener, err := net.Listen("tcp", *instanceListen)
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Println("Listening on", listener.Addr())
+
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ logrus.WithError(err).Error("listener.Accept failed")
+ continue
+ }
+
+ port, err := pRouter.AuthenticatedConnect(conn, "", pineconeRouter.PeerTypeRemote)
+ if err != nil {
+ logrus.WithError(err).Error("pSwitch.AuthenticatedConnect failed")
+ continue
+ }
+
+ fmt.Println("Inbound connection", conn.RemoteAddr(), "is connected to port", port)
+ }
+ }()
+
+ pQUIC := pineconeSessions.NewSessions(logger, pRouter)
+ pMulticast := pineconeMulticast.NewMulticast(logger, pRouter)
+ pMulticast.Start()
+
+ var staticPeerAttempts atomic.Uint32
+ var connectToStaticPeer func()
+ connectToStaticPeer = func() {
+ uri := *instancePeer
+ if uri == "" {
+ return
+ }
+ if err := conn.ConnectToPeer(pRouter, uri); err != nil {
+ exp := time.Second * time.Duration(math.Exp2(float64(staticPeerAttempts.Inc())))
+ time.AfterFunc(exp, connectToStaticPeer)
+ } else {
+ staticPeerAttempts.Store(0)
+ }
+ }
+ pRouter.SetDisconnectedCallback(func(port pineconeTypes.SwitchPortID, public pineconeTypes.PublicKey, peertype int, err error) {
+ if peertype == pineconeRouter.PeerTypeRemote && err != nil {
+ staticPeerAttempts.Store(0)
+ time.AfterFunc(time.Second, connectToStaticPeer)
+ }
+ })
+ go connectToStaticPeer()
+
+ cfg := &config.Dendrite{}
+ cfg.Defaults()
+ cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
+ cfg.Global.PrivateKey = sk
+ 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))
+ cfg.UserAPI.DeviceDatabase.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-device.db", *instanceName))
+ cfg.MediaAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-mediaapi.db", *instanceName))
+ cfg.SyncAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-syncapi.db", *instanceName))
+ cfg.RoomServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-roomserver.db", *instanceName))
+ cfg.SigningKeyServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-signingkeyserver.db", *instanceName))
+ cfg.KeyServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-keyserver.db", *instanceName))
+ cfg.FederationSender.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-federationsender.db", *instanceName))
+ cfg.AppServiceAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-appservice.db", *instanceName))
+ cfg.Global.Kafka.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-naffka.db", *instanceName))
+ if err := cfg.Derive(); err != nil {
+ panic(err)
+ }
+
+ base := setup.NewBaseDendrite(cfg, "Monolith", false)
+ defer base.Close() // nolint: errcheck
+
+ accountDB := base.CreateAccountsDB()
+ federation := conn.CreateFederationClient(base, pQUIC)
+
+ serverKeyAPI := &signing.YggdrasilKeys{}
+ keyRing := serverKeyAPI.KeyRing()
+
+ rsComponent := roomserver.NewInternalAPI(
+ base, keyRing,
+ )
+ rsAPI := rsComponent
+ fsAPI := federationsender.NewInternalAPI(
+ base, federation, rsAPI, keyRing,
+ )
+
+ keyAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, fsAPI)
+ userAPI := userapi.NewInternalAPI(accountDB, &cfg.UserAPI, nil, keyAPI)
+ keyAPI.SetUserAPI(userAPI)
+
+ eduInputAPI := eduserver.NewInternalAPI(
+ base, cache.New(), userAPI,
+ )
+
+ asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
+
+ rsComponent.SetFederationSenderAPI(fsAPI)
+
+ monolith := setup.Monolith{
+ Config: base.Cfg,
+ AccountDB: accountDB,
+ Client: conn.CreateClient(base, pQUIC),
+ FedClient: federation,
+ KeyRing: keyRing,
+
+ AppserviceAPI: asAPI,
+ EDUInternalAPI: eduInputAPI,
+ FederationSenderAPI: fsAPI,
+ RoomserverAPI: rsAPI,
+ UserAPI: userAPI,
+ KeyAPI: keyAPI,
+ ExtPublicRoomsProvider: rooms.NewPineconeRoomProvider(pRouter, pQUIC, fsAPI, federation),
+ }
+ monolith.AddAllPublicRoutes(
+ base.ProcessContext,
+ base.PublicClientAPIMux,
+ base.PublicFederationAPIMux,
+ base.PublicKeyAPIMux,
+ base.PublicMediaAPIMux,
+ )
+
+ wsUpgrader := websocket.Upgrader{}
+ httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
+ httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
+ httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
+ httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
+ httpRouter.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
+ c, err := wsUpgrader.Upgrade(w, r, nil)
+ if err != nil {
+ logrus.WithError(err).Error("Failed to upgrade WebSocket connection")
+ return
+ }
+ conn := conn.WrapWebSocketConn(c)
+ if _, err = pRouter.AuthenticatedConnect(conn, "websocket", pineconeRouter.PeerTypeRemote); err != nil {
+ logrus.WithError(err).Error("Failed to connect WebSocket peer to Pinecone switch")
+ }
+ })
+ embed.Embed(httpRouter, *instancePort, "Pinecone Demo")
+
+ pMux := mux.NewRouter().SkipClean(true).UseEncodedPath()
+ pMux.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.PublicFederationAPIMux)
+ pMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
+
+ pHTTP := pQUIC.HTTP()
+ pHTTP.Mux().Handle(httputil.PublicFederationPathPrefix, pMux)
+ pHTTP.Mux().Handle(httputil.PublicMediaPathPrefix, pMux)
+
+ // Build both ends of a HTTP multiplex.
+ httpServer := &http.Server{
+ Addr: ":0",
+ TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
+ ReadTimeout: 10 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ IdleTimeout: 60 * time.Second,
+ BaseContext: func(_ net.Listener) context.Context {
+ return context.Background()
+ },
+ Handler: pMux,
+ }
+
+ go func() {
+ pubkey := pRouter.PublicKey()
+ logrus.Info("Listening on ", hex.EncodeToString(pubkey[:]))
+ logrus.Fatal(httpServer.Serve(pQUIC))
+ }()
+ go func() {
+ httpBindAddr := fmt.Sprintf(":%d", *instancePort)
+ logrus.Info("Listening on ", httpBindAddr)
+ logrus.Fatal(http.ListenAndServe(httpBindAddr, httpRouter))
+ }()
+ go func() {
+ logrus.Info("Sending wake-up message to known nodes")
+ req := &api.PerformBroadcastEDURequest{}
+ res := &api.PerformBroadcastEDUResponse{}
+ if err := fsAPI.PerformBroadcastEDU(context.TODO(), req, res); err != nil {
+ logrus.WithError(err).Error("Failed to send wake-up message to known nodes")
+ }
+ }()
+
+ base.WaitForShutdown()
+}
diff --git a/cmd/dendrite-demo-pinecone/rooms/rooms.go b/cmd/dendrite-demo-pinecone/rooms/rooms.go
new file mode 100644
index 00000000..002e4393
--- /dev/null
+++ b/cmd/dendrite-demo-pinecone/rooms/rooms.go
@@ -0,0 +1,150 @@
+// 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 rooms
+
+import (
+ "context"
+ "crypto/ed25519"
+ "encoding/hex"
+ "sync"
+ "time"
+
+ "github.com/matrix-org/dendrite/federationsender/api"
+ "github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/util"
+
+ pineconeRouter "github.com/matrix-org/pinecone/router"
+ pineconeSessions "github.com/matrix-org/pinecone/sessions"
+)
+
+const pineconeRoomAttempts = 3
+
+type PineconeRoomProvider struct {
+ r *pineconeRouter.Router
+ s *pineconeSessions.Sessions
+ fedSender api.FederationSenderInternalAPI
+ fedClient *gomatrixserverlib.FederationClient
+}
+
+func NewPineconeRoomProvider(
+ r *pineconeRouter.Router,
+ s *pineconeSessions.Sessions,
+ fedSender api.FederationSenderInternalAPI,
+ fedClient *gomatrixserverlib.FederationClient,
+) *PineconeRoomProvider {
+ p := &PineconeRoomProvider{
+ r: r,
+ s: s,
+ fedSender: fedSender,
+ fedClient: fedClient,
+ }
+ return p
+}
+
+func (p *PineconeRoomProvider) Rooms() []gomatrixserverlib.PublicRoom {
+ known := []ed25519.PublicKey{}
+ for _, k := range p.r.KnownNodes() {
+ known = append(known, k[:])
+ }
+ known = append(known, p.s.Sessions()...)
+ list := []gomatrixserverlib.ServerName{}
+ for _, k := range known {
+ if len(k) == ed25519.PublicKeySize {
+ list = append(list, gomatrixserverlib.ServerName(hex.EncodeToString(k)))
+ }
+ }
+ return bulkFetchPublicRoomsFromServers(context.Background(), p.fedClient, list)
+}
+
+// bulkFetchPublicRoomsFromServers fetches public rooms from the list of homeservers.
+// Returns a list of public rooms.
+func bulkFetchPublicRoomsFromServers(
+ ctx context.Context, fedClient *gomatrixserverlib.FederationClient,
+ homeservers []gomatrixserverlib.ServerName,
+) (publicRooms []gomatrixserverlib.PublicRoom) {
+ limit := 200
+ // follow pipeline semantics, see https://blog.golang.org/pipelines for more info.
+ // goroutines send rooms to this channel
+ roomCh := make(chan gomatrixserverlib.PublicRoom, int(limit))
+ // signalling channel to tell goroutines to stop sending rooms and quit
+ done := make(chan bool)
+ // signalling to say when we can close the room channel
+ var wg sync.WaitGroup
+ wg.Add(len(homeservers))
+ // concurrently query for public rooms
+ for _, hs := range homeservers {
+ go func(homeserverDomain gomatrixserverlib.ServerName) {
+ defer wg.Done()
+ util.GetLogger(ctx).WithField("hs", homeserverDomain).Info("Querying HS for public rooms")
+ var fres gomatrixserverlib.RespPublicRooms
+ var err error
+ for i := 0; i < pineconeRoomAttempts; i++ {
+ fres, err = fedClient.GetPublicRooms(ctx, homeserverDomain, int(limit), "", false, "")
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).WithField("hs", homeserverDomain).Warn(
+ "bulkFetchPublicRoomsFromServers: failed to query hs",
+ )
+ if i == pineconeRoomAttempts-1 {
+ return
+ }
+ } else {
+ break
+ }
+ }
+ for _, room := range fres.Chunk {
+ // atomically send a room or stop
+ select {
+ case roomCh <- room:
+ case <-done:
+ util.GetLogger(ctx).WithError(err).WithField("hs", homeserverDomain).Info("Interrupted whilst sending rooms")
+ return
+ }
+ }
+ }(hs)
+ }
+
+ // Close the room channel when the goroutines have quit so we don't leak, but don't let it stop the in-flight request.
+ // This also allows the request to fail fast if all HSes experience errors as it will cause the room channel to be
+ // closed.
+ go func() {
+ wg.Wait()
+ util.GetLogger(ctx).Info("Cleaning up resources")
+ close(roomCh)
+ }()
+
+ // fan-in results with timeout. We stop when we reach the limit.
+FanIn:
+ for len(publicRooms) < int(limit) || limit == 0 {
+ // add a room or timeout
+ select {
+ case room, ok := <-roomCh:
+ if !ok {
+ util.GetLogger(ctx).Info("All homeservers have been queried, returning results.")
+ break FanIn
+ }
+ publicRooms = append(publicRooms, room)
+ case <-time.After(5 * time.Second): // we've waited long enough, let's tell the client what we got.
+ util.GetLogger(ctx).Info("Waited 5s for federated public rooms, returning early")
+ break FanIn
+ case <-ctx.Done(): // the client hung up on us, let's stop.
+ util.GetLogger(ctx).Info("Client hung up, returning early")
+ break FanIn
+ }
+ }
+ // tell goroutines to stop
+ close(done)
+
+ return publicRooms
+}
diff --git a/cmd/dendrite-demo-yggdrasil/README.md b/cmd/dendrite-demo-yggdrasil/README.md
index 148b9a58..33df7e60 100644
--- a/cmd/dendrite-demo-yggdrasil/README.md
+++ b/cmd/dendrite-demo-yggdrasil/README.md
@@ -1,6 +1,6 @@
# Yggdrasil Demo
-This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.13 or later.
+This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.14 or later.
To run the homeserver, start at the root of the Dendrite repository and run:
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 1099bc83..352c73ff 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -25,7 +25,7 @@ use in production environments just yet!
Dendrite requires:
-* Go 1.13 or higher
+* Go 1.14 or higher
* Postgres 9.6 or higher (if using Postgres databases, not needed for SQLite)
If you want to run a polylith deployment, you also need:
diff --git a/go.mod b/go.mod
index 16c25ead..14eb8aab 100644
--- a/go.mod
+++ b/go.mod
@@ -7,6 +7,7 @@ require (
github.com/getsentry/sentry-go v0.10.0
github.com/gologme/log v1.2.0
github.com/gorilla/mux v1.8.0
+ github.com/gorilla/websocket v1.4.2
github.com/hashicorp/golang-lru v0.5.4
github.com/lib/pq v1.9.0
github.com/libp2p/go-libp2p v0.13.0
@@ -17,13 +18,14 @@ require (
github.com/libp2p/go-libp2p-kad-dht v0.11.1
github.com/libp2p/go-libp2p-pubsub v0.4.1
github.com/libp2p/go-libp2p-record v0.1.3
- github.com/lucas-clemente/quic-go v0.17.3
+ github.com/lucas-clemente/quic-go v0.19.3
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b
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/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd
github.com/matrix-org/gomatrixserverlib v0.0.0-20210302161955-6142fe3f8c2c
github.com/matrix-org/naffka v0.0.0-20201009174903-d26a3b9cb161
+ github.com/matrix-org/pinecone v0.0.0-20210506095321-0f5e444d3861
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
github.com/mattn/go-sqlite3 v1.14.7-0.20210414154423-1157a4212dcb
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
@@ -41,8 +43,9 @@ require (
go.uber.org/atomic v1.7.0
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
+ golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69 // indirect
gopkg.in/h2non/bimg.v1 v1.1.5
gopkg.in/yaml.v2 v2.4.0
)
-go 1.13
+go 1.14
diff --git a/go.sum b/go.sum
index f245a270..2c6906dc 100644
--- a/go.sum
+++ b/go.sum
@@ -24,6 +24,9 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
+github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
+github.com/RyanCarrier/dijkstra v1.0.0/go.mod h1:5agGUBNEtUAGIANmbw09fuO3a2htPEkc1jNH01qxCWA=
+github.com/RyanCarrier/dijkstra-1 v0.0.0-20170512020943-0e5801a26345/go.mod h1:OK4EvWJ441LQqGzed5NGB6vKBAE34n3z7iayPcEwr30=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
@@ -36,11 +39,27 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/albertorestifo/dijkstra v0.0.0-20160910063646-aba76f725f72/go.mod h1:o+JdB7VetTHjLhU0N57x18B9voDBQe0paApdEAEoEfw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
+github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
+github.com/anacrolix/envpprof v1.1.1 h1:sHQCyj7HtiSfaZAzL2rJrQdyS7odLqlwO6nhk/tG/j8=
+github.com/anacrolix/envpprof v1.1.1/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4=
+github.com/anacrolix/log v0.3.0 h1:Btxh7GkT4JYWvWJ1uKOwgobf+7q/1eFQaDdCUXCtssw=
+github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
+github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
+github.com/anacrolix/missinggo v1.2.1 h1:0IE3TqX5y5D0IxeMwTyIgqdDew4QrzcXaaEnJQyjHvw=
+github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y=
+github.com/anacrolix/missinggo/perf v1.0.0 h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy6BqESAJVw=
+github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ=
+github.com/anacrolix/sync v0.2.0 h1:oRe22/ZB+v7v/5Mbc4d2zE0AXEZy0trKyKLjqYOt6tY=
+github.com/anacrolix/sync v0.2.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
+github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
+github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@@ -63,6 +82,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
+github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
+github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
+github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8=
+github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
@@ -119,7 +142,9 @@ github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70d
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
@@ -144,7 +169,6 @@ github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNp
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
-github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
@@ -152,8 +176,9 @@ github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBav
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/sentry-go v0.10.0 h1:6gwY+66NHKqyZrdi6O2jGdo7wGdo9b3B69E01NFgT5g=
github.com/getsentry/sentry-go v0.10.0/go.mod h1:kELm/9iCblqUYh+ZRML7PNdCvEuw24wBvJPYyi86cws=
@@ -161,6 +186,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
+github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@@ -185,13 +212,15 @@ github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=
+github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -213,6 +242,7 @@ github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8/go.mod h1:gq31gQ8wEHkR
github.com/gologme/log v1.2.0 h1:Ya5Ip/KD6FX7uH0S31QO87nCCSucKtF44TLbTtO7V4c=
github.com/gologme/log v1.2.0/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -239,6 +269,7 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -291,6 +322,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hjson/hjson-go v3.0.2-0.20200316202735-d5d0e8b0617d+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
+github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
+github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
@@ -385,6 +419,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
@@ -640,8 +675,8 @@ github.com/libp2p/go-yamux/v2 v2.0.0 h1:vSGhAy5u6iHBq11ZDcyHH4Blcf9xlBhT4WQDoOE9
github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
-github.com/lucas-clemente/quic-go v0.17.3 h1:jMX/MmDNCljfisgMmPGUcBJ+zUh9w3d3ia4YJjYS3TM=
-github.com/lucas-clemente/quic-go v0.17.3/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
+github.com/lucas-clemente/quic-go v0.19.3 h1:eCDQqvGBB+kCTkA0XrAFtNe81FMa0/fn4QSoeAbmiF4=
+github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
@@ -652,9 +687,11 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
-github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ=
-github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk=
+github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
+github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl55b2pc=
+github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs=
+github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07VxbSabxn5A5gZQ=
+github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b h1:xpcmnpfUImRC4O2SAS/dmTcJENDXvGmLUzey76V1R3Q=
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b/go.mod h1:NgPCr+UavRGH6n5jmdX8DuqFZ4JiCWIJoZiuhTRLSUg=
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 h1:eqE5OnGx9ZMWmrRbD3KF/3KtTunw0iQulI7YxOIdxo4=
@@ -668,6 +705,8 @@ github.com/matrix-org/gomatrixserverlib v0.0.0-20210302161955-6142fe3f8c2c h1:vW
github.com/matrix-org/gomatrixserverlib v0.0.0-20210302161955-6142fe3f8c2c/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
github.com/matrix-org/naffka v0.0.0-20201009174903-d26a3b9cb161 h1:h1XVh05pLoC+nJjP3GIpj5wUsuC8WdHP3He0RTkRJTs=
github.com/matrix-org/naffka v0.0.0-20201009174903-d26a3b9cb161/go.mod h1:sjyPyRxKM5uw1nD2cJ6O2OxI6GOqyVBfNXqKjBZTBZE=
+github.com/matrix-org/pinecone v0.0.0-20210506095321-0f5e444d3861 h1:NzU37cIE0LGFbJWY91so3DkqypQ4UAUiSoeVottJPCg=
+github.com/matrix-org/pinecone v0.0.0-20210506095321-0f5e444d3861/go.mod h1:/RVMcZt8gwFhJCQSStLOE48Kd/ABLjFr7XePkNA45k4=
github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
@@ -687,6 +726,7 @@ github.com/mattn/go-sqlite3 v1.14.2/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71
github.com/mattn/go-sqlite3 v1.14.7-0.20210414154423-1157a4212dcb h1:ax2vG2unlxsjwS7PMRo4FECIfAdQLowd6ejWYwPQhBo=
github.com/mattn/go-sqlite3 v1.14.7-0.20210414154423-1157a4212dcb/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237/go.mod h1:UOnLAUmVG5paym8pD3C4B9BQylUDC2vXFJJpT7JrlEA=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
@@ -725,6 +765,7 @@ github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4=
@@ -789,6 +830,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
+github.com/neilalexander/utp v0.1.1-0.20210315133037-94aa85fe0436 h1:1gP/M2jAATYqlKjSbDBlB+EZmlAjzF50pxb5ILor1cs=
+github.com/neilalexander/utp v0.1.1-0.20210315133037-94aa85fe0436/go.mod h1:ylsx0342RjGHjOoVKhR/wz/7Lhiusonihfj4QLxEMcU=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6 h1:evlcQnJY+v8XRRchV3hXzpHDl6GcEZeLXAhlH9Csdww=
@@ -803,16 +846,16 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
-github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
+github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
-github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
+github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
@@ -830,6 +873,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
+github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -887,6 +931,7 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -920,6 +965,7 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -947,6 +993,7 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -969,6 +1016,7 @@ github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/sjson v1.0.3/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y=
github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE=
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
+github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=
github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
@@ -1000,6 +1048,7 @@ github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
+github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
@@ -1098,7 +1147,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -1115,7 +1163,9 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
@@ -1159,6 +1209,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1168,11 +1219,13 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210105210732-16f7687f5001/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1208,8 +1261,9 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1263,6 +1317,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
@@ -1302,6 +1357,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=