cwtch/server/server.go

95 lines
2.8 KiB
Go

package server
import (
"cwtch.im/cwtch/server/fetch"
"cwtch.im/cwtch/server/listen"
"cwtch.im/cwtch/server/metrics"
"cwtch.im/cwtch/server/send"
"cwtch.im/cwtch/storage"
"git.openprivacy.ca/openprivacy/libricochet-go/application"
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
"git.openprivacy.ca/openprivacy/libricochet-go/log"
"os"
"strconv"
"time"
)
// Server encapsulates a complete, compliant Cwtch server.
type Server struct {
app *application.RicochetApplication
config Config
metricsPack metrics.Monitors
}
// 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, serverConfig Config) {
s.config = serverConfig
cwtchserver := new(application.RicochetApplication)
s.metricsPack.Start(cwtchserver, serverConfig.ConfigDir, s.config.ServerReporting.LogMetricsToFile)
af := application.ApplicationInstanceFactory{}
af.Init()
ms := new(storage.MessageStore)
err := ms.Init(serverConfig.ConfigDir, s.config.MaxBufferLines, s.metricsPack.MessageCounter)
if err != nil {
log.Errorln(err)
acn.Close()
os.Exit(1)
}
af.AddHandler("im.cwtch.server.listen", func(rai *application.ApplicationInstance) func() channels.Handler {
return func() channels.Handler {
cslc := new(listen.CwtchServerListenChannel)
return cslc
}
})
af.AddHandler("im.cwtch.server.fetch", func(rai *application.ApplicationInstance) func() channels.Handler {
si := new(Instance)
si.Init(rai, cwtchserver, ms)
return func() channels.Handler {
cssc := new(fetch.CwtchServerFetchChannel)
cssc.Handler = si
return cssc
}
})
af.AddHandler("im.cwtch.server.send", func(rai *application.ApplicationInstance) func() channels.Handler {
si := new(Instance)
si.Init(rai, cwtchserver, ms)
return func() channels.Handler {
cssc := new(send.CwtchServerSendChannel)
cssc.Handler = si
return cssc
}
})
addressIdentity := utils.GetTorV3Hostname(s.config.PublicKey)
cwtchserver.Init(acn, "cwtch server for "+addressIdentity, s.config.Identity(), af, new(application.AcceptAllContactManager))
port := strconv.Itoa(application.RicochetPort)
log.Infof("cwtch server running on cwtch:%s\n", addressIdentity+".onion:"+port)
s.app = cwtchserver
for true {
listenService, err := acn.Listen(s.config.PrivateKey, application.RicochetPort)
if err != nil {
log.Errorf("Listen() error setting up onion service: %v\n", err)
} else {
s.app.Run(listenService)
}
time.Sleep(5 * time.Second)
}
}
// Shutdown kills the app closing all connections and freeing all goroutines
func (s *Server) Shutdown() {
s.app.Shutdown()
s.metricsPack.Stop()
}