Add gobind builds for Yggdrasil demo

This commit is contained in:
Neil Alexander 2020-06-11 16:44:36 +01:00
parent 89d61c4877
commit b6a591127e
7 changed files with 267 additions and 57 deletions

6
build/gobind/build.sh Normal file
View file

@ -0,0 +1,6 @@
#!/bin/sh
gomobile bind -v \
-ldflags "-X $github.com/yggdrasil-network/yggdrasil-go/src/version.buildName=riot-ios-p2p" \
-target ios \
github.com/matrix-org/dendrite/build/gobind

153
build/gobind/monolith.go Normal file
View file

@ -0,0 +1,153 @@
package gobind
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"time"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn"
"github.com/matrix-org/dendrite/eduserver"
"github.com/matrix-org/dendrite/eduserver/cache"
"github.com/matrix-org/dendrite/federationsender"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/basecomponent"
"github.com/matrix-org/dendrite/internal/config"
"github.com/matrix-org/dendrite/internal/setup"
"github.com/matrix-org/dendrite/publicroomsapi/storage"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/gomatrixserverlib"
"github.com/sirupsen/logrus"
)
type DendriteMonolith struct {
StorageDirectory string
listener net.Listener
}
func (m *DendriteMonolith) BaseURL() string {
return fmt.Sprintf("http://%s", m.listener.Addr().String())
}
func (m *DendriteMonolith) Start() {
logger := logrus.Logger{
Out: BindLogger{},
}
var err error
m.listener, err = net.Listen("tcp", "localhost:0")
if err != nil {
panic(err)
}
// Build both ends of a HTTP multiplex.
httpServer := &http.Server{
Addr: ":0",
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
ReadTimeout: 15 * time.Second,
WriteTimeout: 45 * time.Second,
IdleTimeout: 60 * time.Second,
BaseContext: func(_ net.Listener) context.Context {
return context.Background()
},
}
ygg, err := yggconn.Setup("dendrite", "", m.StorageDirectory)
if err != nil {
panic(err)
}
cfg := &config.Dendrite{}
cfg.SetDefaults()
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
cfg.Kafka.UseNaffka = true
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
cfg.Kafka.Topics.OutputTypingEvent = "typingServerOutput"
cfg.Database.Account = config.DataSource(fmt.Sprintf("file:%s/dendrite-account.db", m.StorageDirectory))
cfg.Database.Device = config.DataSource(fmt.Sprintf("file:%s/dendrite-device.db", m.StorageDirectory))
cfg.Database.MediaAPI = config.DataSource(fmt.Sprintf("file:%s/dendrite-mediaapi.db", m.StorageDirectory))
cfg.Database.SyncAPI = config.DataSource(fmt.Sprintf("file:%s/dendrite-syncapi.db", m.StorageDirectory))
cfg.Database.RoomServer = config.DataSource(fmt.Sprintf("file:%s/dendrite-roomserver.db", m.StorageDirectory))
cfg.Database.ServerKey = config.DataSource(fmt.Sprintf("file:%s/dendrite-serverkey.db", m.StorageDirectory))
cfg.Database.FederationSender = config.DataSource(fmt.Sprintf("file:%s/dendrite-federationsender.db", m.StorageDirectory))
cfg.Database.AppService = config.DataSource(fmt.Sprintf("file:%s/dendrite-appservice.db", m.StorageDirectory))
cfg.Database.PublicRoomsAPI = config.DataSource(fmt.Sprintf("file:%s/dendrite-publicroomsa.db", m.StorageDirectory))
cfg.Database.Naffka = config.DataSource(fmt.Sprintf("file:%s/dendrite-naffka.db", m.StorageDirectory))
if err = cfg.Derive(); err != nil {
panic(err)
}
base := basecomponent.NewBaseDendrite(cfg, "Monolith", false)
defer base.Close() // nolint: errcheck
accountDB := base.CreateAccountsDB()
deviceDB := base.CreateDeviceDB()
federation := ygg.CreateFederationClient(base)
serverKeyAPI := &signing.YggdrasilKeys{}
keyRing := serverKeyAPI.KeyRing()
rsComponent := roomserver.NewInternalAPI(
base, keyRing, federation,
)
rsAPI := rsComponent
eduInputAPI := eduserver.NewInternalAPI(
base, cache.New(), deviceDB,
)
asAPI := appservice.NewInternalAPI(base, accountDB, deviceDB, rsAPI)
fsAPI := federationsender.NewInternalAPI(
base, federation, rsAPI, keyRing,
)
rsComponent.SetFederationSenderAPI(fsAPI)
publicRoomsDB, err := storage.NewPublicRoomsServerDatabase(string(base.Cfg.Database.PublicRoomsAPI), base.Cfg.DbProperties(), cfg.Matrix.ServerName)
if err != nil {
logger.WithError(err).Panicf("failed to connect to public rooms db")
}
monolith := setup.Monolith{
Config: base.Cfg,
AccountDB: accountDB,
DeviceDB: deviceDB,
FedClient: federation,
KeyRing: keyRing,
KafkaConsumer: base.KafkaConsumer,
KafkaProducer: base.KafkaProducer,
AppserviceAPI: asAPI,
EDUInternalAPI: eduInputAPI,
FederationSenderAPI: fsAPI,
RoomserverAPI: rsAPI,
PublicRoomsDB: publicRoomsDB,
}
monolith.AddAllPublicRoutes(base.PublicAPIMux)
internal.SetupHTTPAPI(
http.DefaultServeMux,
base.PublicAPIMux,
base.InternalAPIMux,
cfg,
base.UseHTTPAPIs,
)
go func() {
logger.Info("Listening on ", ygg.DerivedServerName())
logger.Fatal(httpServer.Serve(ygg))
}()
go func() {
logger.Info("Listening on ", m.BaseURL())
logger.Fatal(http.Serve(m.listener, nil))
}()
}

View file

@ -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
}

View file

@ -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
}

View file

@ -16,18 +16,14 @@ package main
import ( import (
"context" "context"
"crypto/ed25519"
"crypto/tls" "crypto/tls"
"encoding/hex"
"flag" "flag"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"strings"
"time" "time"
"github.com/matrix-org/dendrite/appservice" "github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/embed" "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/embed"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing" "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn" "github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn"
@ -51,46 +47,6 @@ var (
instancePeer = flag.String("peer", "", "an internet Yggdrasil peer to connect to") instancePeer = flag.String("peer", "", "an internet Yggdrasil peer to connect to")
) )
type yggroundtripper struct {
inner *http.Transport
}
func (y *yggroundtripper) RoundTrip(req *http.Request) (*http.Response, error) {
req.URL.Scheme = "http"
return y.inner.RoundTrip(req)
}
func createFederationClient(
base *basecomponent.BaseDendrite, n *yggconn.Node,
) *gomatrixserverlib.FederationClient {
yggdialer := func(_, 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)
}
yggdialerctx := func(ctx context.Context, network, address string) (net.Conn, error) {
return yggdialer(network, address)
}
tr := &http.Transport{}
tr.RegisterProtocol(
"matrix", &yggroundtripper{
inner: &http.Transport{
ResponseHeaderTimeout: 15 * time.Second,
IdleConnTimeout: 60 * time.Second,
DialContext: yggdialerctx,
},
},
)
return gomatrixserverlib.NewFederationClientWithTransport(
base.Cfg.Matrix.ServerName, base.Cfg.Matrix.KeyID, base.Cfg.Matrix.PrivateKey, tr,
)
}
// nolint:gocyclo // nolint:gocyclo
func main() { func main() {
flag.Parse() flag.Parse()
@ -107,7 +63,7 @@ func main() {
}, },
} }
ygg, err := yggconn.Setup(*instanceName, *instancePeer) ygg, err := yggconn.Setup(*instanceName, *instancePeer, ".")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -140,7 +96,7 @@ func main() {
accountDB := base.CreateAccountsDB() accountDB := base.CreateAccountsDB()
deviceDB := base.CreateDeviceDB() deviceDB := base.CreateDeviceDB()
federation := createFederationClient(base, ygg) federation := ygg.CreateFederationClient(base)
serverKeyAPI := &signing.YggdrasilKeys{} serverKeyAPI := &signing.YggdrasilKeys{}
keyRing := serverKeyAPI.KeyRing() keyRing := serverKeyAPI.KeyRing()

View file

@ -0,0 +1,56 @@
package yggconn
import (
"context"
"crypto/ed25519"
"encoding/hex"
"fmt"
"net"
"net/http"
"strings"
"time"
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
"github.com/matrix-org/dendrite/internal/basecomponent"
"github.com/matrix-org/gomatrixserverlib"
)
type yggroundtripper struct {
inner *http.Transport
}
func (y *yggroundtripper) RoundTrip(req *http.Request) (*http.Response, error) {
req.URL.Scheme = "http"
return y.inner.RoundTrip(req)
}
func (n *Node) CreateFederationClient(
base *basecomponent.BaseDendrite,
) *gomatrixserverlib.FederationClient {
yggdialer := func(_, 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)
}
yggdialerctx := func(ctx context.Context, network, address string) (net.Conn, error) {
return yggdialer(network, address)
}
tr := &http.Transport{}
tr.RegisterProtocol(
"matrix", &yggroundtripper{
inner: &http.Transport{
ResponseHeaderTimeout: 15 * time.Second,
IdleConnTimeout: 60 * time.Second,
DialContext: yggdialerctx,
},
},
)
return gomatrixserverlib.NewFederationClientWithTransport(
base.Cfg.Matrix.ServerName, base.Cfg.Matrix.KeyID, base.Cfg.Matrix.PrivateKey, tr,
)
}

View file

@ -49,7 +49,7 @@ type Node struct {
} }
// nolint:gocyclo // nolint:gocyclo
func Setup(instanceName, instancePeer string) (*Node, error) { func Setup(instanceName, instancePeer, storageDirectory string) (*Node, error) {
n := &Node{ n := &Node{
core: &yggdrasil.Core{}, core: &yggdrasil.Core{},
config: yggdrasilconfig.GenerateConfig(), config: yggdrasilconfig.GenerateConfig(),
@ -59,7 +59,7 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
incoming: make(chan *yamux.Stream), incoming: make(chan *yamux.Stream),
} }
yggfile := fmt.Sprintf("%s-yggdrasil.conf", instanceName) yggfile := fmt.Sprintf("%s/%s-yggdrasil.conf", storageDirectory, instanceName)
if _, err := os.Stat(yggfile); !os.IsNotExist(err) { if _, err := os.Stat(yggfile); !os.IsNotExist(err) {
yggconf, e := ioutil.ReadFile(yggfile) yggconf, e := ioutil.ReadFile(yggfile)
if e != nil { if e != nil {
@ -69,7 +69,7 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
panic(err) panic(err)
} }
} else { } else {
n.config.AdminListen = fmt.Sprintf("unix://./%s-yggdrasil.sock", instanceName) n.config.AdminListen = "none" // fmt.Sprintf("unix://%s/%s-yggdrasil.sock", storageDirectory, instanceName)
n.config.MulticastInterfaces = []string{".*"} n.config.MulticastInterfaces = []string{".*"}
n.config.EncryptionPrivateKey = hex.EncodeToString(n.EncryptionPrivateKey()) n.config.EncryptionPrivateKey = hex.EncodeToString(n.EncryptionPrivateKey())
n.config.EncryptionPublicKey = hex.EncodeToString(n.EncryptionPublicKey()) n.config.EncryptionPublicKey = hex.EncodeToString(n.EncryptionPublicKey())
@ -96,20 +96,22 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
panic(err) panic(err)
} }
} }
/*
if err = n.admin.Init(n.core, n.state, n.log, nil); err != nil { if err = n.admin.Init(n.core, n.state, n.log, nil); err != nil {
panic(err) panic(err)
} }
if err = n.admin.Start(); err != nil { if err = n.admin.Start(); err != nil {
panic(err) panic(err)
} }
*/
if err = n.multicast.Init(n.core, n.state, n.log, nil); err != nil { if err = n.multicast.Init(n.core, n.state, n.log, nil); err != nil {
panic(err) panic(err)
} }
if err = n.multicast.Start(); err != nil { if err = n.multicast.Start(); err != nil {
panic(err) panic(err)
} }
n.admin.SetupAdminHandlers(n.admin) //n.admin.SetupAdminHandlers(n.admin)
n.multicast.SetupAdminHandlers(n.admin) //n.multicast.SetupAdminHandlers(n.admin)
n.listener, err = n.core.ConnListen() n.listener, err = n.core.ConnListen()
if err != nil { if err != nil {
panic(err) panic(err)