2018-02-07 19:32:11 +01:00
|
|
|
package daemon
|
2017-10-01 23:30:48 +02:00
|
|
|
|
|
|
|
import (
|
2017-10-10 00:54:14 +02:00
|
|
|
"crypto/tls"
|
2017-12-14 21:30:07 +01:00
|
|
|
"net/http"
|
2017-10-01 23:30:48 +02:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2017-10-10 00:54:14 +02:00
|
|
|
"time"
|
2017-10-01 23:30:48 +02:00
|
|
|
|
2017-10-10 00:54:14 +02:00
|
|
|
"golang.org/x/crypto/acme/autocert"
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
serverDaemon "dev.sum7.eu/genofire/yaja/daemon/server"
|
2018-02-07 15:34:18 +01:00
|
|
|
"dev.sum7.eu/genofire/yaja/database"
|
|
|
|
"dev.sum7.eu/genofire/yaja/server/extension"
|
2017-10-02 14:38:52 +02:00
|
|
|
|
2018-02-07 15:34:18 +01:00
|
|
|
"dev.sum7.eu/genofire/golang-lib/file"
|
|
|
|
"dev.sum7.eu/genofire/golang-lib/worker"
|
|
|
|
"dev.sum7.eu/genofire/yaja/server"
|
2017-10-01 23:30:48 +02:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
2017-10-10 00:54:14 +02:00
|
|
|
var (
|
2018-02-07 19:32:11 +01:00
|
|
|
serverConfig = &serverDaemon.Config{}
|
2017-12-17 17:50:51 +01:00
|
|
|
db = &database.State{}
|
|
|
|
srv *server.Server
|
|
|
|
certs *tls.Config
|
|
|
|
extensionsClient extension.Extensions
|
|
|
|
extensionsServer extension.Extensions
|
2017-10-10 00:54:14 +02:00
|
|
|
)
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
// ServerCMD represents the serve command
|
|
|
|
var ServerCMD = &cobra.Command{
|
2017-12-14 21:30:07 +01:00
|
|
|
Use: "server",
|
2018-02-07 19:32:11 +01:00
|
|
|
Short: "runs xmpp server",
|
|
|
|
Example: "yaja daemon server -c /etc/yaja.conf",
|
2017-10-01 23:30:48 +02:00
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
2017-12-17 17:50:51 +01:00
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
if err := file.ReadTOML(configPath, serverConfig); err != nil {
|
2017-10-02 14:38:52 +02:00
|
|
|
log.Fatal("unable to load config file:", err)
|
|
|
|
}
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
log.SetLevel(serverConfig.Logging.Level)
|
2017-12-14 21:30:07 +01:00
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
if err := file.ReadJSON(serverConfig.StatePath, db); err != nil {
|
2017-10-10 00:54:14 +02:00
|
|
|
log.Warn("unable to load state file:", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
statesaveWorker = worker.NewWorker(time.Minute, func() {
|
2018-02-07 19:32:11 +01:00
|
|
|
file.SaveJSON(serverConfig.StatePath, db)
|
|
|
|
log.Info("save state to:", serverConfig.StatePath)
|
2017-10-10 00:54:14 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
m := autocert.Manager{
|
2018-02-07 19:32:11 +01:00
|
|
|
Cache: autocert.DirCache(serverConfig.TLSDir),
|
2017-10-10 00:54:14 +02:00
|
|
|
Prompt: autocert.AcceptTOS,
|
|
|
|
}
|
|
|
|
|
2017-12-14 21:30:07 +01:00
|
|
|
// https server to handle acme (by letsencrypt)
|
2018-02-07 19:32:11 +01:00
|
|
|
for _, addr := range serverConfig.Address.Webserver {
|
2017-12-15 22:24:42 +01:00
|
|
|
hs := &http.Server{
|
|
|
|
Addr: addr,
|
|
|
|
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
|
|
|
}
|
|
|
|
go func(hs *http.Server, addr string) {
|
|
|
|
if err := hs.ListenAndServeTLS("", ""); err != http.ErrServerClosed {
|
|
|
|
log.Errorf("webserver with addr %s: %s", addr, err)
|
|
|
|
}
|
|
|
|
}(hs, addr)
|
2017-12-14 21:30:07 +01:00
|
|
|
}
|
2017-10-10 00:54:14 +02:00
|
|
|
|
|
|
|
srv = &server.Server{
|
2017-12-17 17:50:51 +01:00
|
|
|
TLSManager: &m,
|
|
|
|
Database: db,
|
2018-02-07 19:32:11 +01:00
|
|
|
ClientAddr: serverConfig.Address.Client,
|
|
|
|
ServerAddr: serverConfig.Address.Server,
|
|
|
|
LoggingClient: serverConfig.Logging.LevelClient,
|
|
|
|
LoggingServer: serverConfig.Logging.LevelServer,
|
|
|
|
RegisterEnable: serverConfig.Register.Enable,
|
|
|
|
RegisterDomains: serverConfig.Register.Domains,
|
2017-12-17 17:50:51 +01:00
|
|
|
ExtensionsServer: extensionsServer,
|
|
|
|
ExtensionsClient: extensionsClient,
|
2017-10-10 00:54:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
go statesaveWorker.Start()
|
|
|
|
go srv.Start()
|
|
|
|
|
2017-10-02 14:38:52 +02:00
|
|
|
log.Infoln("yaja started ")
|
2017-10-01 23:30:48 +02:00
|
|
|
|
|
|
|
// Wait for INT/TERM
|
|
|
|
sigs := make(chan os.Signal, 1)
|
2017-10-10 00:54:14 +02:00
|
|
|
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGUSR1)
|
|
|
|
for sig := range sigs {
|
|
|
|
log.Infoln("received", sig)
|
|
|
|
switch sig {
|
|
|
|
case syscall.SIGTERM:
|
|
|
|
log.Panic("terminated")
|
|
|
|
os.Exit(0)
|
|
|
|
case syscall.SIGQUIT:
|
|
|
|
quit()
|
|
|
|
case syscall.SIGHUP:
|
|
|
|
quit()
|
|
|
|
case syscall.SIGUSR1:
|
|
|
|
reload()
|
|
|
|
}
|
|
|
|
}
|
2017-10-01 23:30:48 +02:00
|
|
|
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2017-10-10 00:54:14 +02:00
|
|
|
func quit() {
|
|
|
|
srv.Close()
|
|
|
|
statesaveWorker.Close()
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
file.SaveJSON(serverConfig.StatePath, db)
|
2017-10-10 00:54:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func reload() {
|
|
|
|
log.Info("start reloading...")
|
2018-02-07 19:32:11 +01:00
|
|
|
var configNewData *serverDaemon.Config
|
2017-12-17 17:50:51 +01:00
|
|
|
|
|
|
|
if err := file.ReadTOML(configPath, configNewData); err != nil {
|
2017-10-10 00:54:14 +02:00
|
|
|
log.Warn("unable to load config file:", err)
|
|
|
|
return
|
|
|
|
}
|
2017-12-15 22:24:42 +01:00
|
|
|
log.SetLevel(configNewData.Logging.Level)
|
|
|
|
srv.LoggingClient = configNewData.Logging.LevelClient
|
2017-12-17 17:50:51 +01:00
|
|
|
srv.LoggingServer = configNewData.Logging.LevelServer
|
2017-12-15 22:24:42 +01:00
|
|
|
srv.RegisterEnable = configNewData.Register.Enable
|
|
|
|
srv.RegisterDomains = configNewData.Register.Domains
|
2017-10-10 00:54:14 +02:00
|
|
|
|
2017-12-14 21:30:07 +01:00
|
|
|
//TODO fetch changing address (to set restart)
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
if configNewData.StatePath != serverConfig.StatePath {
|
2017-10-10 00:54:14 +02:00
|
|
|
statesaveWorker.Close()
|
|
|
|
statesaveWorker := worker.NewWorker(time.Minute, func() {
|
2017-12-14 21:30:07 +01:00
|
|
|
file.SaveJSON(configNewData.StatePath, db)
|
2017-10-10 00:54:14 +02:00
|
|
|
log.Info("save state to:", configNewData.StatePath)
|
|
|
|
})
|
|
|
|
go statesaveWorker.Start()
|
|
|
|
}
|
|
|
|
|
|
|
|
restartServer := false
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
if configNewData.TLSDir != serverConfig.TLSDir {
|
2017-10-10 00:54:14 +02:00
|
|
|
|
|
|
|
m := autocert.Manager{
|
2018-02-07 19:32:11 +01:00
|
|
|
Cache: autocert.DirCache(serverConfig.TLSDir),
|
2017-10-10 00:54:14 +02:00
|
|
|
Prompt: autocert.AcceptTOS,
|
|
|
|
}
|
|
|
|
|
|
|
|
certs = &tls.Config{GetCertificate: m.GetCertificate}
|
|
|
|
restartServer = true
|
|
|
|
}
|
|
|
|
if restartServer {
|
2017-12-15 22:24:42 +01:00
|
|
|
newServer := &server.Server{
|
2017-12-17 17:50:51 +01:00
|
|
|
TLSConfig: certs,
|
|
|
|
Database: db,
|
|
|
|
ClientAddr: configNewData.Address.Client,
|
|
|
|
ServerAddr: configNewData.Address.Server,
|
|
|
|
LoggingClient: configNewData.Logging.LevelClient,
|
|
|
|
RegisterEnable: configNewData.Register.Enable,
|
|
|
|
RegisterDomains: configNewData.Register.Domains,
|
|
|
|
ExtensionsServer: extensionsServer,
|
|
|
|
ExtensionsClient: extensionsClient,
|
2017-12-15 22:24:42 +01:00
|
|
|
}
|
|
|
|
log.Warn("reloading need a restart:")
|
|
|
|
go newServer.Start()
|
2017-10-10 00:54:14 +02:00
|
|
|
//TODO should fetch new server error
|
|
|
|
srv.Close()
|
|
|
|
srv = newServer
|
|
|
|
}
|
|
|
|
|
2018-02-07 19:32:11 +01:00
|
|
|
serverConfig = configNewData
|
2017-10-10 00:54:14 +02:00
|
|
|
log.Info("reloaded")
|
|
|
|
}
|
|
|
|
|
2017-10-01 23:30:48 +02:00
|
|
|
func init() {
|
2018-02-10 13:34:42 +01:00
|
|
|
|
2017-12-17 17:50:51 +01:00
|
|
|
extensionsClient = append(extensionsClient,
|
2017-12-17 13:31:02 +01:00
|
|
|
&extension.Message{},
|
2017-12-17 15:39:36 +01:00
|
|
|
&extension.Presence{},
|
2017-12-17 13:31:02 +01:00
|
|
|
extension.IQExtensions{
|
2018-02-10 13:34:42 +01:00
|
|
|
//&extension.IQPrivateBookmark{},
|
|
|
|
//&extension.IQPrivateMetacontact{},
|
|
|
|
//&extension.IQPrivateRoster{},
|
2017-12-17 15:39:36 +01:00
|
|
|
&extension.IQPing{},
|
2018-02-10 13:34:42 +01:00
|
|
|
//&extension.IQLast{},
|
|
|
|
//&extension.IQDisco{Database: db},
|
|
|
|
//&extension.IQRoster{Database: db},
|
|
|
|
//&extension.IQExtensionDiscovery{GetSpaces: func() []string {
|
|
|
|
// return extensionsClient.Spaces()
|
|
|
|
//}},
|
2017-12-17 13:31:02 +01:00
|
|
|
})
|
|
|
|
|
2017-12-17 17:50:51 +01:00
|
|
|
extensionsServer = append(extensionsServer,
|
|
|
|
extension.IQExtensions{
|
|
|
|
&extension.IQPing{},
|
|
|
|
})
|
2018-02-14 02:49:41 +01:00
|
|
|
ServerCMD.Flags().StringVarP(&configPath, "config", "c", "yaja-server.conf", "path to configuration file")
|
2017-12-16 23:20:46 +01:00
|
|
|
|
2017-10-01 23:30:48 +02:00
|
|
|
}
|