forked from cwtch.im/cwtch
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
package server
|
|
|
|
import (
|
|
"crypto/ed25519"
|
|
"cwtch.im/cwtch/model"
|
|
"cwtch.im/cwtch/server/metrics"
|
|
"cwtch.im/cwtch/server/storage"
|
|
"cwtch.im/tapir"
|
|
"cwtch.im/tapir/applications"
|
|
tor2 "cwtch.im/tapir/networks/tor"
|
|
"cwtch.im/tapir/persistence"
|
|
"cwtch.im/tapir/primitives"
|
|
"cwtch.im/tapir/primitives/privacypass"
|
|
"git.openprivacy.ca/openprivacy/connectivity"
|
|
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// Server encapsulates a complete, compliant Cwtch server.
|
|
type Server struct {
|
|
service tapir.Service
|
|
config Config
|
|
metricsPack metrics.Monitors
|
|
closed bool
|
|
tokenTapirService tapir.Service
|
|
tokenServer *privacypass.TokenServer
|
|
tokenService primitives.Identity
|
|
tokenServicePrivKey ed25519.PrivateKey
|
|
}
|
|
|
|
// Setup initialized a server from a given configuration
|
|
func (s *Server) Setup(serverConfig Config) {
|
|
s.config = serverConfig
|
|
bs := new(persistence.BoltPersistence)
|
|
bs.Open("./tokens.db")
|
|
s.tokenServer = privacypass.NewTokenServerFromStore(bs)
|
|
s.tokenService = s.config.TokenServiceIdentity()
|
|
s.tokenServicePrivKey = s.config.TokenServerPrivateKey
|
|
}
|
|
|
|
// Run starts a server with the given privateKey
|
|
// TODO: surface errors
|
|
// TODO: handle HUP/KILL signals to exit and close Tor gracefully
|
|
// TODO: handle user input to exit
|
|
func (s *Server) Run(acn connectivity.ACN) {
|
|
s.closed = false
|
|
|
|
addressIdentity := tor.GetTorV3Hostname(s.config.PublicKey)
|
|
|
|
//tokenService := privacypass.NewTokenServer()
|
|
identity := primitives.InitializeIdentity("", &s.config.PrivateKey, &s.config.PublicKey)
|
|
var service tapir.Service
|
|
service = new(tor2.BaseOnionService)
|
|
service.Init(acn, s.config.PrivateKey, &identity)
|
|
s.service = service
|
|
log.Infof("cwtch server running on cwtch:%s\n", addressIdentity+".onion:")
|
|
s.metricsPack.Start(service, s.config.ConfigDir, s.config.ServerReporting.LogMetricsToFile)
|
|
|
|
ms := new(storage.MessageStore)
|
|
err := ms.Init(s.config.ConfigDir, s.config.MaxBufferLines, s.metricsPack.MessageCounter)
|
|
if err != nil {
|
|
log.Errorln(err)
|
|
acn.Close()
|
|
os.Exit(1)
|
|
}
|
|
|
|
go func() {
|
|
s.tokenTapirService = new(tor2.BaseOnionService)
|
|
s.tokenTapirService.Init(acn, s.tokenServicePrivKey, &s.tokenService)
|
|
tokenApplication := new(applications.TokenApplication)
|
|
tokenApplication.TokenService = s.tokenServer
|
|
powTokenApp := new(applications.ApplicationChain).
|
|
ChainApplication(new(applications.ProofOfWorkApplication), applications.SuccessfulProofOfWorkCapability).
|
|
ChainApplication(tokenApplication, applications.HasTokensCapability)
|
|
s.tokenTapirService.Listen(powTokenApp)
|
|
}()
|
|
|
|
for true {
|
|
s.service.Listen(NewTokenBoardServer(ms, s.tokenServer))
|
|
if s.closed {
|
|
return
|
|
}
|
|
time.Sleep(5 * time.Second)
|
|
}
|
|
}
|
|
|
|
// KeyBundle provides the signed keybundle of the server
|
|
func (s *Server) KeyBundle() *model.KeyBundle {
|
|
kb := model.NewKeyBundle()
|
|
identity := s.config.Identity()
|
|
kb.Keys[model.KeyTypeServerOnion] = model.Key(identity.Hostname())
|
|
kb.Keys[model.KeyTypeTokenOnion] = model.Key(s.tokenService.Hostname())
|
|
kb.Keys[model.KeyTypePrivacyPass] = model.Key(s.tokenServer.Y.String())
|
|
kb.Sign(identity)
|
|
return kb
|
|
}
|
|
|
|
// Shutdown kills the app closing all connections and freeing all goroutines
|
|
func (s *Server) Shutdown() {
|
|
s.closed = true
|
|
s.service.Shutdown()
|
|
s.tokenTapirService.Shutdown()
|
|
s.metricsPack.Stop()
|
|
}
|