2018-03-09 20:44:13 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2018-05-28 18:05:06 +00:00
|
|
|
"cwtch.im/cwtch/server/fetch"
|
|
|
|
"cwtch.im/cwtch/server/listen"
|
2018-06-27 15:14:59 +00:00
|
|
|
"cwtch.im/cwtch/server/metrics"
|
2018-05-28 18:05:06 +00:00
|
|
|
"cwtch.im/cwtch/server/send"
|
2019-01-21 20:11:40 +00:00
|
|
|
"cwtch.im/cwtch/server/storage"
|
2018-06-23 16:15:36 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
2018-11-10 22:14:12 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
2018-11-24 01:58:45 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
|
|
|
|
2018-12-04 02:52:11 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
|
|
|
"os"
|
2018-11-24 01:58:45 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
2018-03-09 20:44:13 +00:00
|
|
|
)
|
|
|
|
|
2018-05-16 21:11:04 +00:00
|
|
|
// Server encapsulates a complete, compliant Cwtch server.
|
2018-03-09 20:44:13 +00:00
|
|
|
type Server struct {
|
2018-06-27 15:14:59 +00:00
|
|
|
app *application.RicochetApplication
|
2018-10-05 03:18:34 +00:00
|
|
|
config Config
|
2018-06-27 15:14:59 +00:00
|
|
|
metricsPack metrics.Monitors
|
2019-02-04 22:18:24 +00:00
|
|
|
closed bool
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2018-06-03 19:36:20 +00:00
|
|
|
// Run starts a server with the given privateKey
|
2018-05-16 21:11:04 +00:00
|
|
|
// TODO: surface errors
|
2018-11-10 22:14:12 +00:00
|
|
|
// TODO: handle HUP/KILL signals to exit and close Tor gracefully
|
|
|
|
// TODO: handle user input to exit
|
2018-11-22 18:01:04 +00:00
|
|
|
func (s *Server) Run(acn connectivity.ACN, serverConfig Config) {
|
2019-02-04 22:18:24 +00:00
|
|
|
s.closed = false
|
2018-06-18 22:57:21 +00:00
|
|
|
s.config = serverConfig
|
2018-03-09 20:44:13 +00:00
|
|
|
cwtchserver := new(application.RicochetApplication)
|
2018-11-01 20:22:29 +00:00
|
|
|
s.metricsPack.Start(cwtchserver, serverConfig.ConfigDir, s.config.ServerReporting.LogMetricsToFile)
|
2018-03-09 20:44:13 +00:00
|
|
|
|
2019-01-23 20:50:53 +00:00
|
|
|
af := application.InstanceFactory{}
|
2018-03-09 20:44:13 +00:00
|
|
|
af.Init()
|
|
|
|
ms := new(storage.MessageStore)
|
2018-11-24 01:58:45 +00:00
|
|
|
err := ms.Init(serverConfig.ConfigDir, s.config.MaxBufferLines, s.metricsPack.MessageCounter)
|
2018-09-20 21:01:46 +00:00
|
|
|
if err != nil {
|
2018-12-04 02:52:11 +00:00
|
|
|
log.Errorln(err)
|
|
|
|
acn.Close()
|
|
|
|
os.Exit(1)
|
2018-09-20 21:01:46 +00:00
|
|
|
}
|
2019-01-23 20:50:53 +00:00
|
|
|
af.AddHandler("im.cwtch.server.listen", func(rai *application.Instance) func() channels.Handler {
|
2018-03-09 20:44:13 +00:00
|
|
|
return func() channels.Handler {
|
|
|
|
cslc := new(listen.CwtchServerListenChannel)
|
|
|
|
return cslc
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-01-23 20:50:53 +00:00
|
|
|
af.AddHandler("im.cwtch.server.fetch", func(rai *application.Instance) func() channels.Handler {
|
2018-03-14 22:23:35 +00:00
|
|
|
si := new(Instance)
|
2018-03-09 20:44:13 +00:00
|
|
|
si.Init(rai, cwtchserver, ms)
|
|
|
|
return func() channels.Handler {
|
|
|
|
cssc := new(fetch.CwtchServerFetchChannel)
|
|
|
|
cssc.Handler = si
|
|
|
|
return cssc
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-01-23 20:50:53 +00:00
|
|
|
af.AddHandler("im.cwtch.server.send", func(rai *application.Instance) func() channels.Handler {
|
2018-03-14 22:23:35 +00:00
|
|
|
si := new(Instance)
|
2018-03-09 20:44:13 +00:00
|
|
|
si.Init(rai, cwtchserver, ms)
|
|
|
|
return func() channels.Handler {
|
|
|
|
cssc := new(send.CwtchServerSendChannel)
|
|
|
|
cssc.Handler = si
|
|
|
|
return cssc
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2018-11-24 01:58:45 +00:00
|
|
|
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)
|
2018-12-04 02:52:11 +00:00
|
|
|
log.Infof("cwtch server running on cwtch:%s\n", addressIdentity+".onion:"+port)
|
2018-11-24 01:58:45 +00:00
|
|
|
|
2018-05-30 18:42:17 +00:00
|
|
|
s.app = cwtchserver
|
2018-11-24 01:58:45 +00:00
|
|
|
|
|
|
|
for true {
|
|
|
|
listenService, err := acn.Listen(s.config.PrivateKey, application.RicochetPort)
|
|
|
|
if err != nil {
|
2018-12-04 02:52:11 +00:00
|
|
|
log.Errorf("Listen() error setting up onion service: %v\n", err)
|
2018-11-24 01:58:45 +00:00
|
|
|
} else {
|
|
|
|
s.app.Run(listenService)
|
|
|
|
}
|
2019-02-04 22:18:24 +00:00
|
|
|
if s.closed {
|
|
|
|
return
|
|
|
|
}
|
2018-11-24 01:58:45 +00:00
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
}
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
2018-05-30 18:42:17 +00:00
|
|
|
|
2018-06-15 16:21:07 +00:00
|
|
|
// Shutdown kills the app closing all connections and freeing all goroutines
|
2018-05-30 18:42:17 +00:00
|
|
|
func (s *Server) Shutdown() {
|
2019-02-04 22:18:24 +00:00
|
|
|
s.closed = true
|
2018-05-30 18:42:17 +00:00
|
|
|
s.app.Shutdown()
|
2018-06-27 15:14:59 +00:00
|
|
|
s.metricsPack.Stop()
|
2018-05-30 18:42:17 +00:00
|
|
|
}
|