Svc -> Service
This commit is contained in:
parent
d98290c17f
commit
1827dda0c6
@ -15,14 +15,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type addressLister struct {
|
type addressLister struct {
|
||||||
upnpSvc *upnpSvc
|
upnpService *upnpService
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddressLister(upnpSvc *upnpSvc, cfg *config.Wrapper) *addressLister {
|
func newAddressLister(upnpService *upnpService, cfg *config.Wrapper) *addressLister {
|
||||||
return &addressLister{
|
return &addressLister{
|
||||||
upnpSvc: upnpSvc,
|
upnpService: upnpService,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,10 +73,10 @@ func (e *addressLister) addresses(includePrivateIPV4 bool) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an external port mapping from the upnpSvc, if it has one. If so,
|
// Get an external port mapping from the upnpService, if it has one. If so,
|
||||||
// add it as another unspecified address.
|
// add it as another unspecified address.
|
||||||
if e.upnpSvc != nil {
|
if e.upnpService != nil {
|
||||||
if port := e.upnpSvc.ExternalPort(); port != 0 {
|
if port := e.upnpService.ExternalPort(); port != 0 {
|
||||||
addrs = append(addrs, fmt.Sprintf("tcp://:%d", port))
|
addrs = append(addrs, fmt.Sprintf("tcp://:%d", port))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,17 +13,17 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/events"
|
"github.com/syncthing/syncthing/lib/events"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The auditSvc subscribes to events and writes these in JSON format, one
|
// The auditService subscribes to events and writes these in JSON format, one
|
||||||
// event per line, to the specified writer.
|
// event per line, to the specified writer.
|
||||||
type auditSvc struct {
|
type auditService struct {
|
||||||
w io.Writer // audit destination
|
w io.Writer // audit destination
|
||||||
stop chan struct{} // signals time to stop
|
stop chan struct{} // signals time to stop
|
||||||
started chan struct{} // signals startup complete
|
started chan struct{} // signals startup complete
|
||||||
stopped chan struct{} // signals stop complete
|
stopped chan struct{} // signals stop complete
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAuditSvc(w io.Writer) *auditSvc {
|
func newAuditService(w io.Writer) *auditService {
|
||||||
return &auditSvc{
|
return &auditService{
|
||||||
w: w,
|
w: w,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
started: make(chan struct{}),
|
started: make(chan struct{}),
|
||||||
@ -32,7 +32,7 @@ func newAuditSvc(w io.Writer) *auditSvc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serve runs the audit service.
|
// Serve runs the audit service.
|
||||||
func (s *auditSvc) Serve() {
|
func (s *auditService) Serve() {
|
||||||
defer close(s.stopped)
|
defer close(s.stopped)
|
||||||
sub := events.Default.Subscribe(events.AllEvents)
|
sub := events.Default.Subscribe(events.AllEvents)
|
||||||
defer events.Default.Unsubscribe(sub)
|
defer events.Default.Unsubscribe(sub)
|
||||||
@ -52,18 +52,18 @@ func (s *auditSvc) Serve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the audit service.
|
// Stop stops the audit service.
|
||||||
func (s *auditSvc) Stop() {
|
func (s *auditService) Stop() {
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForStart returns once the audit service is ready to receive events, or
|
// WaitForStart returns once the audit service is ready to receive events, or
|
||||||
// immediately if it's already running.
|
// immediately if it's already running.
|
||||||
func (s *auditSvc) WaitForStart() {
|
func (s *auditService) WaitForStart() {
|
||||||
<-s.started
|
<-s.started
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForStop returns once the audit service has stopped.
|
// WaitForStop returns once the audit service has stopped.
|
||||||
// (Needed by the tests.)
|
// (Needed by the tests.)
|
||||||
func (s *auditSvc) WaitForStop() {
|
func (s *auditService) WaitForStop() {
|
||||||
<-s.stopped
|
<-s.stopped
|
||||||
}
|
}
|
||||||
@ -17,13 +17,13 @@ import (
|
|||||||
|
|
||||||
func TestAuditService(t *testing.T) {
|
func TestAuditService(t *testing.T) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
svc := newAuditSvc(buf)
|
service := newAuditService(buf)
|
||||||
|
|
||||||
// Event sent before start, will not be logged
|
// Event sent before start, will not be logged
|
||||||
events.Default.Log(events.Ping, "the first event")
|
events.Default.Log(events.Ping, "the first event")
|
||||||
|
|
||||||
go svc.Serve()
|
go service.Serve()
|
||||||
svc.WaitForStart()
|
service.WaitForStart()
|
||||||
|
|
||||||
// Event that should end up in the audit log
|
// Event that should end up in the audit log
|
||||||
events.Default.Log(events.Ping, "the second event")
|
events.Default.Log(events.Ping, "the second event")
|
||||||
@ -31,8 +31,8 @@ func TestAuditService(t *testing.T) {
|
|||||||
// We need to give the events time to arrive, since the channels are buffered etc.
|
// We need to give the events time to arrive, since the channels are buffered etc.
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
svc.Stop()
|
service.Stop()
|
||||||
svc.WaitForStop()
|
service.WaitForStop()
|
||||||
|
|
||||||
// This event should not be logged, since we have stopped.
|
// This event should not be logged, since we have stopped.
|
||||||
events.Default.Log(events.Ping, "the third event")
|
events.Default.Log(events.Ping, "the third event")
|
||||||
@ -10,8 +10,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base32"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -50,16 +48,16 @@ var (
|
|||||||
startTime = time.Now()
|
startTime = time.Now()
|
||||||
)
|
)
|
||||||
|
|
||||||
type apiSvc struct {
|
type apiService struct {
|
||||||
id protocol.DeviceID
|
id protocol.DeviceID
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
assetDir string
|
assetDir string
|
||||||
model *model.Model
|
model *model.Model
|
||||||
eventSub *events.BufferedSubscription
|
eventSub *events.BufferedSubscription
|
||||||
discoverer *discover.CachingMux
|
discoverer *discover.CachingMux
|
||||||
relaySvc *relay.Svc
|
relayService *relay.Service
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
fss *folderSummarySvc
|
fss *folderSummaryService
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
systemConfigMut sync.Mutex
|
systemConfigMut sync.Mutex
|
||||||
|
|
||||||
@ -67,26 +65,26 @@ type apiSvc struct {
|
|||||||
systemLog *logger.Recorder
|
systemLog *logger.Recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAPISvc(id protocol.DeviceID, cfg *config.Wrapper, assetDir string, m *model.Model, eventSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc, errors, systemLog *logger.Recorder) (*apiSvc, error) {
|
func newAPIService(id protocol.DeviceID, cfg *config.Wrapper, assetDir string, m *model.Model, eventSub *events.BufferedSubscription, discoverer *discover.CachingMux, relayService *relay.Service, errors, systemLog *logger.Recorder) (*apiService, error) {
|
||||||
svc := &apiSvc{
|
service := &apiService{
|
||||||
id: id,
|
id: id,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
assetDir: assetDir,
|
assetDir: assetDir,
|
||||||
model: m,
|
model: m,
|
||||||
eventSub: eventSub,
|
eventSub: eventSub,
|
||||||
discoverer: discoverer,
|
discoverer: discoverer,
|
||||||
relaySvc: relaySvc,
|
relayService: relayService,
|
||||||
systemConfigMut: sync.NewMutex(),
|
systemConfigMut: sync.NewMutex(),
|
||||||
guiErrors: errors,
|
guiErrors: errors,
|
||||||
systemLog: systemLog,
|
systemLog: systemLog,
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
svc.listener, err = svc.getListener(cfg.GUI())
|
service.listener, err = service.getListener(cfg.GUI())
|
||||||
return svc, err
|
return service, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getListener(guiCfg config.GUIConfiguration) (net.Listener, error) {
|
func (s *apiService) getListener(guiCfg config.GUIConfiguration) (net.Listener, error) {
|
||||||
cert, err := tls.LoadX509KeyPair(locations[locHTTPSCertFile], locations[locHTTPSKeyFile])
|
cert, err := tls.LoadX509KeyPair(locations[locHTTPSCertFile], locations[locHTTPSKeyFile])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Loading HTTPS certificate:", err)
|
l.Infoln("Loading HTTPS certificate:", err)
|
||||||
@ -137,7 +135,7 @@ func sendJSON(w http.ResponseWriter, jsonObject interface{}) {
|
|||||||
json.NewEncoder(w).Encode(jsonObject)
|
json.NewEncoder(w).Encode(jsonObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) Serve() {
|
func (s *apiService) Serve() {
|
||||||
s.stop = make(chan struct{})
|
s.stop = make(chan struct{})
|
||||||
|
|
||||||
// The GET handlers
|
// The GET handlers
|
||||||
@ -231,7 +229,7 @@ func (s *apiSvc) Serve() {
|
|||||||
ReadTimeout: 10 * time.Second,
|
ReadTimeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fss = newFolderSummarySvc(s.cfg, s.model)
|
s.fss = newFolderSummaryService(s.cfg, s.model)
|
||||||
defer s.fss.Stop()
|
defer s.fss.Stop()
|
||||||
s.fss.ServeBackground()
|
s.fss.ServeBackground()
|
||||||
|
|
||||||
@ -249,20 +247,20 @@ func (s *apiSvc) Serve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) Stop() {
|
func (s *apiService) Stop() {
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
s.listener.Close()
|
s.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) String() string {
|
func (s *apiService) String() string {
|
||||||
return fmt.Sprintf("apiSvc@%p", s)
|
return fmt.Sprintf("apiService@%p", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) VerifyConfiguration(from, to config.Configuration) error {
|
func (s *apiService) VerifyConfiguration(from, to config.Configuration) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) CommitConfiguration(from, to config.Configuration) bool {
|
func (s *apiService) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
if to.GUI == from.GUI {
|
if to.GUI == from.GUI {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -372,11 +370,11 @@ func withDetailsMiddleware(id protocol.DeviceID, h http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) restPing(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) restPing(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, map[string]string{"ping": "pong"})
|
sendJSON(w, map[string]string{"ping": "pong"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, map[string]string{
|
sendJSON(w, map[string]string{
|
||||||
"version": Version,
|
"version": Version,
|
||||||
"codename": Codename,
|
"codename": Codename,
|
||||||
@ -386,7 +384,7 @@ func (s *apiSvc) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemDebug(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemDebug(w http.ResponseWriter, r *http.Request) {
|
||||||
names := l.Facilities()
|
names := l.Facilities()
|
||||||
enabled := l.FacilityDebugging()
|
enabled := l.FacilityDebugging()
|
||||||
sort.Strings(enabled)
|
sort.Strings(enabled)
|
||||||
@ -396,7 +394,7 @@ func (s *apiSvc) getSystemDebug(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemDebug(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemDebug(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
for _, f := range strings.Split(q.Get("enable"), ",") {
|
for _, f := range strings.Split(q.Get("enable"), ",") {
|
||||||
@ -415,7 +413,7 @@ func (s *apiSvc) postSystemDebug(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBBrowse(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBBrowse(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
prefix := qs.Get("prefix")
|
prefix := qs.Get("prefix")
|
||||||
@ -429,7 +427,7 @@ func (s *apiSvc) getDBBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, s.model.GlobalDirectoryTree(folder, prefix, levels, dirsonly))
|
sendJSON(w, s.model.GlobalDirectoryTree(folder, prefix, levels, dirsonly))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var folder = qs.Get("folder")
|
var folder = qs.Get("folder")
|
||||||
var deviceStr = qs.Get("device")
|
var deviceStr = qs.Get("device")
|
||||||
@ -445,7 +443,7 @@ func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
sendJSON(w, folderSummary(s.cfg, s.model, folder))
|
sendJSON(w, folderSummary(s.cfg, s.model, folder))
|
||||||
@ -490,13 +488,13 @@ func folderSummary(cfg *config.Wrapper, m *model.Model, folder string) map[strin
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postDBOverride(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postDBOverride(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var folder = qs.Get("folder")
|
var folder = qs.Get("folder")
|
||||||
go s.model.Override(folder)
|
go s.model.Override(folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBNeed(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBNeed(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
|
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
@ -523,19 +521,19 @@ func (s *apiSvc) getDBNeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, s.model.ConnectionStats())
|
sendJSON(w, s.model.ConnectionStats())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDeviceStats(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDeviceStats(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, s.model.DeviceStatistics())
|
sendJSON(w, s.model.DeviceStatistics())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getFolderStats(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getFolderStats(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, s.model.FolderStatistics())
|
sendJSON(w, s.model.FolderStatistics())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBFile(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
file := qs.Get("file")
|
file := qs.Get("file")
|
||||||
@ -550,11 +548,11 @@ func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, s.cfg.Raw())
|
sendJSON(w, s.cfg.Raw())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
s.systemConfigMut.Lock()
|
s.systemConfigMut.Lock()
|
||||||
defer s.systemConfigMut.Unlock()
|
defer s.systemConfigMut.Unlock()
|
||||||
|
|
||||||
@ -597,16 +595,16 @@ func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.cfg.Save()
|
s.cfg.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, map[string]bool{"configInSync": configInSync})
|
sendJSON(w, map[string]bool{"configInSync": configInSync})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemRestart(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemRestart(w http.ResponseWriter, r *http.Request) {
|
||||||
s.flushResponse(`{"ok": "restarting"}`, w)
|
s.flushResponse(`{"ok": "restarting"}`, w)
|
||||||
go restart()
|
go restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemReset(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemReset(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
|
|
||||||
@ -632,12 +630,12 @@ func (s *apiSvc) postSystemReset(w http.ResponseWriter, r *http.Request) {
|
|||||||
go restart()
|
go restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemShutdown(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemShutdown(w http.ResponseWriter, r *http.Request) {
|
||||||
s.flushResponse(`{"ok": "shutting down"}`, w)
|
s.flushResponse(`{"ok": "shutting down"}`, w)
|
||||||
go shutdown()
|
go shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) flushResponse(resp string, w http.ResponseWriter) {
|
func (s *apiService) flushResponse(resp string, w http.ResponseWriter) {
|
||||||
w.Write([]byte(resp + "\n"))
|
w.Write([]byte(resp + "\n"))
|
||||||
f := w.(http.Flusher)
|
f := w.(http.Flusher)
|
||||||
f.Flush()
|
f.Flush()
|
||||||
@ -646,7 +644,7 @@ func (s *apiSvc) flushResponse(resp string, w http.ResponseWriter) {
|
|||||||
var cpuUsagePercent [10]float64 // The last ten seconds
|
var cpuUsagePercent [10]float64 // The last ten seconds
|
||||||
var cpuUsageLock = sync.NewRWMutex()
|
var cpuUsageLock = sync.NewRWMutex()
|
||||||
|
|
||||||
func (s *apiSvc) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
var m runtime.MemStats
|
var m runtime.MemStats
|
||||||
runtime.ReadMemStats(&m)
|
runtime.ReadMemStats(&m)
|
||||||
|
|
||||||
@ -670,12 +668,12 @@ func (s *apiSvc) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
res["discoveryMethods"] = discoMethods
|
res["discoveryMethods"] = discoMethods
|
||||||
res["discoveryErrors"] = discoErrors
|
res["discoveryErrors"] = discoErrors
|
||||||
}
|
}
|
||||||
if s.relaySvc != nil {
|
if s.relayService != nil {
|
||||||
res["relaysEnabled"] = true
|
res["relaysEnabled"] = true
|
||||||
relayClientStatus := make(map[string]bool)
|
relayClientStatus := make(map[string]bool)
|
||||||
relayClientLatency := make(map[string]int)
|
relayClientLatency := make(map[string]int)
|
||||||
for _, relay := range s.relaySvc.Relays() {
|
for _, relay := range s.relayService.Relays() {
|
||||||
latency, ok := s.relaySvc.RelayStatus(relay)
|
latency, ok := s.relayService.RelayStatus(relay)
|
||||||
relayClientStatus[relay] = ok
|
relayClientStatus[relay] = ok
|
||||||
relayClientLatency[relay] = int(latency / time.Millisecond)
|
relayClientLatency[relay] = int(latency / time.Millisecond)
|
||||||
}
|
}
|
||||||
@ -696,23 +694,23 @@ func (s *apiSvc) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, res)
|
sendJSON(w, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemError(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemError(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, map[string][]logger.Line{
|
sendJSON(w, map[string][]logger.Line{
|
||||||
"errors": s.guiErrors.Since(time.Time{}),
|
"errors": s.guiErrors.Since(time.Time{}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemError(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemError(w http.ResponseWriter, r *http.Request) {
|
||||||
bs, _ := ioutil.ReadAll(r.Body)
|
bs, _ := ioutil.ReadAll(r.Body)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
l.Warnln(string(bs))
|
l.Warnln(string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemErrorClear(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemErrorClear(w http.ResponseWriter, r *http.Request) {
|
||||||
s.guiErrors.Clear()
|
s.guiErrors.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemLog(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemLog(w http.ResponseWriter, r *http.Request) {
|
||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
@ -721,7 +719,7 @@ func (s *apiSvc) getSystemLog(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemLogTxt(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemLogTxt(w http.ResponseWriter, r *http.Request) {
|
||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
@ -732,7 +730,7 @@ func (s *apiSvc) getSystemLogTxt(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemHTTPMetrics(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemHTTPMetrics(w http.ResponseWriter, r *http.Request) {
|
||||||
stats := make(map[string]interface{})
|
stats := make(map[string]interface{})
|
||||||
metrics.Each(func(name string, intf interface{}) {
|
metrics.Each(func(name string, intf interface{}) {
|
||||||
if m, ok := intf.(*metrics.StandardTimer); ok {
|
if m, ok := intf.(*metrics.StandardTimer); ok {
|
||||||
@ -752,7 +750,7 @@ func (s *apiSvc) getSystemHTTPMetrics(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(bs)
|
w.Write(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||||
devices := make(map[string]discover.CacheEntry)
|
devices := make(map[string]discover.CacheEntry)
|
||||||
|
|
||||||
if s.discoverer != nil {
|
if s.discoverer != nil {
|
||||||
@ -767,11 +765,11 @@ func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, devices)
|
sendJSON(w, devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getReport(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getReport(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, reportData(s.cfg, s.model))
|
sendJSON(w, reportData(s.cfg, s.model))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
|
|
||||||
ignores, patterns, err := s.model.GetIgnores(qs.Get("folder"))
|
ignores, patterns, err := s.model.GetIgnores(qs.Get("folder"))
|
||||||
@ -786,7 +784,7 @@ func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postDBIgnores(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postDBIgnores(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
|
|
||||||
var data map[string][]string
|
var data map[string][]string
|
||||||
@ -807,7 +805,7 @@ func (s *apiSvc) postDBIgnores(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.getDBIgnores(w, r)
|
s.getDBIgnores(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getEvents(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
sinceStr := qs.Get("since")
|
sinceStr := qs.Get("since")
|
||||||
limitStr := qs.Get("limit")
|
limitStr := qs.Get("limit")
|
||||||
@ -829,7 +827,7 @@ func (s *apiSvc) getEvents(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, evs)
|
sendJSON(w, evs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
if noUpgrade {
|
if noUpgrade {
|
||||||
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|
||||||
return
|
return
|
||||||
@ -848,7 +846,7 @@ func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, res)
|
sendJSON(w, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDeviceID(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getDeviceID(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
idStr := qs.Get("id")
|
idStr := qs.Get("id")
|
||||||
id, err := protocol.DeviceIDFromString(idStr)
|
id, err := protocol.DeviceIDFromString(idStr)
|
||||||
@ -864,7 +862,7 @@ func (s *apiSvc) getDeviceID(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getLang(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getLang(w http.ResponseWriter, r *http.Request) {
|
||||||
lang := r.Header.Get("Accept-Language")
|
lang := r.Header.Get("Accept-Language")
|
||||||
var langs []string
|
var langs []string
|
||||||
for _, l := range strings.Split(lang, ",") {
|
for _, l := range strings.Split(lang, ",") {
|
||||||
@ -874,7 +872,7 @@ func (s *apiSvc) getLang(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, langs)
|
sendJSON(w, langs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version)
|
rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("getting latest release:", err)
|
l.Warnln("getting latest release:", err)
|
||||||
@ -896,7 +894,7 @@ func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemPause(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemPause(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var deviceStr = qs.Get("device")
|
var deviceStr = qs.Get("device")
|
||||||
|
|
||||||
@ -909,7 +907,7 @@ func (s *apiSvc) postSystemPause(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.model.PauseDevice(device)
|
s.model.PauseDevice(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemResume(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postSystemResume(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var deviceStr = qs.Get("device")
|
var deviceStr = qs.Get("device")
|
||||||
|
|
||||||
@ -922,7 +920,7 @@ func (s *apiSvc) postSystemResume(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.model.ResumeDevice(device)
|
s.model.ResumeDevice(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postDBScan(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postDBScan(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
if folder != "" {
|
if folder != "" {
|
||||||
@ -948,7 +946,7 @@ func (s *apiSvc) postDBScan(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postDBPrio(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) postDBPrio(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
file := qs.Get("file")
|
file := qs.Get("file")
|
||||||
@ -956,7 +954,7 @@ func (s *apiSvc) postDBPrio(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.getDBNeed(w, r)
|
s.getDBNeed(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getQR(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getQR(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var text = qs.Get("text")
|
var text = qs.Get("text")
|
||||||
code, err := qr.Encode(text, qr.M)
|
code, err := qr.Encode(text, qr.M)
|
||||||
@ -969,7 +967,7 @@ func (s *apiSvc) getQR(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(code.PNG())
|
w.Write(code.PNG())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
||||||
tot := map[string]float64{}
|
tot := map[string]float64{}
|
||||||
count := map[string]float64{}
|
count := map[string]float64{}
|
||||||
|
|
||||||
@ -993,7 +991,7 @@ func (s *apiSvc) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
sendJSON(w, comp)
|
sendJSON(w, comp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
current := qs.Get("current")
|
current := qs.Get("current")
|
||||||
search, _ := osutil.ExpandTilde(current)
|
search, _ := osutil.ExpandTilde(current)
|
||||||
@ -1099,7 +1097,7 @@ func (s embeddedStatic) mimeTypeForFile(file string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) toNeedSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
func (s *apiService) toNeedSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
||||||
res := make([]jsonDBFileInfo, len(fs))
|
res := make([]jsonDBFileInfo, len(fs))
|
||||||
for i, f := range fs {
|
for i, f := range fs {
|
||||||
res[i] = jsonDBFileInfo(f)
|
res[i] = jsonDBFileInfo(f)
|
||||||
@ -1140,11 +1138,8 @@ type jsonVersionVector protocol.Vector
|
|||||||
|
|
||||||
func (v jsonVersionVector) MarshalJSON() ([]byte, error) {
|
func (v jsonVersionVector) MarshalJSON() ([]byte, error) {
|
||||||
res := make([]string, len(v))
|
res := make([]string, len(v))
|
||||||
bs := make([]byte, 8)
|
|
||||||
for i, c := range v {
|
for i, c := range v {
|
||||||
binary.BigEndian.PutUint64(bs, c.ID)
|
res[i] = fmt.Sprintf("%d:%d", c.ID, c.Value)
|
||||||
id := base32.StdEncoding.EncodeToString(bs)
|
|
||||||
res[i] = fmt.Sprintf("%s:%d", id[:7], c.Value)
|
|
||||||
}
|
}
|
||||||
return json.Marshal(res)
|
return json.Marshal(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -511,23 +511,23 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
// Create a main service manager. We'll add things to this as we go along.
|
// Create a main service manager. We'll add things to this as we go along.
|
||||||
// We want any logging it does to go through our log system.
|
// We want any logging it does to go through our log system.
|
||||||
mainSvc := suture.New("main", suture.Spec{
|
mainService := suture.New("main", suture.Spec{
|
||||||
Log: func(line string) {
|
Log: func(line string) {
|
||||||
l.Debugln(line)
|
l.Debugln(line)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
mainSvc.ServeBackground()
|
mainService.ServeBackground()
|
||||||
|
|
||||||
// Set a log prefix similar to the ID we will have later on, or early log
|
// Set a log prefix similar to the ID we will have later on, or early log
|
||||||
// lines look ugly.
|
// lines look ugly.
|
||||||
l.SetPrefix("[start] ")
|
l.SetPrefix("[start] ")
|
||||||
|
|
||||||
if runtimeOptions.auditEnabled {
|
if runtimeOptions.auditEnabled {
|
||||||
startAuditing(mainSvc)
|
startAuditing(mainService)
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtimeOptions.verbose {
|
if runtimeOptions.verbose {
|
||||||
mainSvc.Add(newVerboseSvc())
|
mainService.Add(newVerboseService())
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := logger.NewRecorder(l, logger.LevelWarn, maxSystemErrors, 0)
|
errors := logger.NewRecorder(l, logger.LevelWarn, maxSystemErrors, 0)
|
||||||
@ -731,7 +731,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mainSvc.Add(m)
|
mainService.Add(m)
|
||||||
|
|
||||||
// The default port we announce, possibly modified by setupUPnP next.
|
// The default port we announce, possibly modified by setupUPnP next.
|
||||||
|
|
||||||
@ -752,33 +752,33 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
// Start UPnP
|
// Start UPnP
|
||||||
|
|
||||||
if opts.UPnPEnabled {
|
if opts.UPnPEnabled {
|
||||||
upnpSvc := newUPnPSvc(cfg, addr.Port)
|
upnpService := newUPnPService(cfg, addr.Port)
|
||||||
mainSvc.Add(upnpSvc)
|
mainService.Add(upnpService)
|
||||||
|
|
||||||
// The external address tracker needs to know about the UPnP service
|
// The external address tracker needs to know about the UPnP service
|
||||||
// so it can check for an external mapped port.
|
// so it can check for an external mapped port.
|
||||||
addrList = newAddressLister(upnpSvc, cfg)
|
addrList = newAddressLister(upnpService, cfg)
|
||||||
} else {
|
} else {
|
||||||
addrList = newAddressLister(nil, cfg)
|
addrList = newAddressLister(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start relay management
|
// Start relay management
|
||||||
|
|
||||||
var relaySvc *relay.Svc
|
var relayService *relay.Service
|
||||||
if opts.RelaysEnabled && (opts.GlobalAnnEnabled || opts.RelayWithoutGlobalAnn) {
|
if opts.RelaysEnabled && (opts.GlobalAnnEnabled || opts.RelayWithoutGlobalAnn) {
|
||||||
relaySvc = relay.NewSvc(cfg, tlsCfg)
|
relayService = relay.NewService(cfg, tlsCfg)
|
||||||
mainSvc.Add(relaySvc)
|
mainService.Add(relayService)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start discovery
|
// Start discovery
|
||||||
|
|
||||||
cachedDiscovery := discover.NewCachingMux()
|
cachedDiscovery := discover.NewCachingMux()
|
||||||
mainSvc.Add(cachedDiscovery)
|
mainService.Add(cachedDiscovery)
|
||||||
|
|
||||||
if cfg.Options().GlobalAnnEnabled {
|
if cfg.Options().GlobalAnnEnabled {
|
||||||
for _, srv := range cfg.GlobalDiscoveryServers() {
|
for _, srv := range cfg.GlobalDiscoveryServers() {
|
||||||
l.Infoln("Using discovery server", srv)
|
l.Infoln("Using discovery server", srv)
|
||||||
gd, err := discover.NewGlobal(srv, cert, addrList, relaySvc)
|
gd, err := discover.NewGlobal(srv, cert, addrList, relayService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("Global discovery:", err)
|
l.Warnln("Global discovery:", err)
|
||||||
continue
|
continue
|
||||||
@ -793,14 +793,14 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
if cfg.Options().LocalAnnEnabled {
|
if cfg.Options().LocalAnnEnabled {
|
||||||
// v4 broadcasts
|
// v4 broadcasts
|
||||||
bcd, err := discover.NewLocal(myID, fmt.Sprintf(":%d", cfg.Options().LocalAnnPort), addrList, relaySvc)
|
bcd, err := discover.NewLocal(myID, fmt.Sprintf(":%d", cfg.Options().LocalAnnPort), addrList, relayService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("IPv4 local discovery:", err)
|
l.Warnln("IPv4 local discovery:", err)
|
||||||
} else {
|
} else {
|
||||||
cachedDiscovery.Add(bcd, 0, 0, ipv4LocalDiscoveryPriority)
|
cachedDiscovery.Add(bcd, 0, 0, ipv4LocalDiscoveryPriority)
|
||||||
}
|
}
|
||||||
// v6 multicasts
|
// v6 multicasts
|
||||||
mcd, err := discover.NewLocal(myID, cfg.Options().LocalAnnMCAddr, addrList, relaySvc)
|
mcd, err := discover.NewLocal(myID, cfg.Options().LocalAnnMCAddr, addrList, relayService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("IPv6 local discovery:", err)
|
l.Warnln("IPv6 local discovery:", err)
|
||||||
} else {
|
} else {
|
||||||
@ -810,12 +810,12 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
// GUI
|
// GUI
|
||||||
|
|
||||||
setupGUI(mainSvc, cfg, m, apiSub, cachedDiscovery, relaySvc, errors, systemLog, runtimeOptions)
|
setupGUI(mainService, cfg, m, apiSub, cachedDiscovery, relayService, errors, systemLog, runtimeOptions)
|
||||||
|
|
||||||
// Start connection management
|
// Start connection management
|
||||||
|
|
||||||
connectionSvc := connections.NewConnectionSvc(cfg, myID, m, tlsCfg, cachedDiscovery, relaySvc, bepProtocolName, tlsDefaultCommonName, lans)
|
connectionService := connections.NewConnectionService(cfg, myID, m, tlsCfg, cachedDiscovery, relayService, bepProtocolName, tlsDefaultCommonName, lans)
|
||||||
mainSvc.Add(connectionSvc)
|
mainService.Add(connectionService)
|
||||||
|
|
||||||
if runtimeOptions.cpuProfile {
|
if runtimeOptions.cpuProfile {
|
||||||
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
|
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
|
||||||
@ -875,7 +875,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
code := <-stop
|
code := <-stop
|
||||||
|
|
||||||
mainSvc.Stop()
|
mainService.Stop()
|
||||||
|
|
||||||
l.Okln("Exiting")
|
l.Okln("Exiting")
|
||||||
|
|
||||||
@ -947,24 +947,24 @@ func loadConfig(cfgFile string) (*config.Wrapper, string, error) {
|
|||||||
return cfg, myName, nil
|
return cfg, myName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startAuditing(mainSvc *suture.Supervisor) {
|
func startAuditing(mainService *suture.Supervisor) {
|
||||||
auditFile := timestampedLoc(locAuditLog)
|
auditFile := timestampedLoc(locAuditLog)
|
||||||
fd, err := os.OpenFile(auditFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
|
fd, err := os.OpenFile(auditFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Audit:", err)
|
l.Fatalln("Audit:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
auditSvc := newAuditSvc(fd)
|
auditService := newAuditService(fd)
|
||||||
mainSvc.Add(auditSvc)
|
mainService.Add(auditService)
|
||||||
|
|
||||||
// We wait for the audit service to fully start before we return, to
|
// We wait for the audit service to fully start before we return, to
|
||||||
// ensure we capture all events from the start.
|
// ensure we capture all events from the start.
|
||||||
auditSvc.WaitForStart()
|
auditService.WaitForStart()
|
||||||
|
|
||||||
l.Infoln("Audit log in", auditFile)
|
l.Infoln("Audit log in", auditFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc, errors, systemLog *logger.Recorder, runtimeOptions RuntimeOptions) {
|
func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relayService *relay.Service, errors, systemLog *logger.Recorder, runtimeOptions RuntimeOptions) {
|
||||||
guiCfg := cfg.GUI()
|
guiCfg := cfg.GUI()
|
||||||
|
|
||||||
if !guiCfg.Enabled {
|
if !guiCfg.Enabled {
|
||||||
@ -975,12 +975,12 @@ func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, a
|
|||||||
l.Warnln("Insecure admin access is enabled.")
|
l.Warnln("Insecure admin access is enabled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
api, err := newAPISvc(myID, cfg, runtimeOptions.assetDir, m, apiSub, discoverer, relaySvc, errors, systemLog)
|
api, err := newAPIService(myID, cfg, runtimeOptions.assetDir, m, apiSub, discoverer, relayService, errors, systemLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Cannot start GUI:", err)
|
l.Fatalln("Cannot start GUI:", err)
|
||||||
}
|
}
|
||||||
cfg.Subscribe(api)
|
cfg.Subscribe(api)
|
||||||
mainSvc.Add(api)
|
mainService.Add(api)
|
||||||
|
|
||||||
if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting {
|
if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting {
|
||||||
// Can potentially block if the utility we are invoking doesn't
|
// Can potentially block if the utility we are invoking doesn't
|
||||||
|
|||||||
@ -16,9 +16,9 @@ import (
|
|||||||
"github.com/thejerf/suture"
|
"github.com/thejerf/suture"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The folderSummarySvc adds summary information events (FolderSummary and
|
// The folderSummaryService adds summary information events (FolderSummary and
|
||||||
// FolderCompletion) into the event stream at certain intervals.
|
// FolderCompletion) into the event stream at certain intervals.
|
||||||
type folderSummarySvc struct {
|
type folderSummaryService struct {
|
||||||
*suture.Supervisor
|
*suture.Supervisor
|
||||||
|
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
@ -35,9 +35,9 @@ type folderSummarySvc struct {
|
|||||||
lastEventReqMut sync.Mutex
|
lastEventReqMut sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFolderSummarySvc(cfg *config.Wrapper, m *model.Model) *folderSummarySvc {
|
func newFolderSummaryService(cfg *config.Wrapper, m *model.Model) *folderSummaryService {
|
||||||
svc := &folderSummarySvc{
|
service := &folderSummaryService{
|
||||||
Supervisor: suture.NewSimple("folderSummarySvc"),
|
Supervisor: suture.NewSimple("folderSummaryService"),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
model: m,
|
model: m,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
@ -47,20 +47,20 @@ func newFolderSummarySvc(cfg *config.Wrapper, m *model.Model) *folderSummarySvc
|
|||||||
lastEventReqMut: sync.NewMutex(),
|
lastEventReqMut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.Add(serviceFunc(svc.listenForUpdates))
|
service.Add(serviceFunc(service.listenForUpdates))
|
||||||
svc.Add(serviceFunc(svc.calculateSummaries))
|
service.Add(serviceFunc(service.calculateSummaries))
|
||||||
|
|
||||||
return svc
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *folderSummarySvc) Stop() {
|
func (c *folderSummaryService) Stop() {
|
||||||
c.Supervisor.Stop()
|
c.Supervisor.Stop()
|
||||||
close(c.stop)
|
close(c.stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// listenForUpdates subscribes to the event bus and makes note of folders that
|
// listenForUpdates subscribes to the event bus and makes note of folders that
|
||||||
// need their data recalculated.
|
// need their data recalculated.
|
||||||
func (c *folderSummarySvc) listenForUpdates() {
|
func (c *folderSummaryService) listenForUpdates() {
|
||||||
sub := events.Default.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged)
|
sub := events.Default.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged)
|
||||||
defer events.Default.Unsubscribe(sub)
|
defer events.Default.Unsubscribe(sub)
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ func (c *folderSummarySvc) listenForUpdates() {
|
|||||||
|
|
||||||
// calculateSummaries periodically recalculates folder summaries and
|
// calculateSummaries periodically recalculates folder summaries and
|
||||||
// completion percentage, and sends the results on the event bus.
|
// completion percentage, and sends the results on the event bus.
|
||||||
func (c *folderSummarySvc) calculateSummaries() {
|
func (c *folderSummaryService) calculateSummaries() {
|
||||||
const pumpInterval = 2 * time.Second
|
const pumpInterval = 2 * time.Second
|
||||||
pump := time.NewTimer(pumpInterval)
|
pump := time.NewTimer(pumpInterval)
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ func (c *folderSummarySvc) calculateSummaries() {
|
|||||||
|
|
||||||
// foldersToHandle returns the list of folders needing a summary update, and
|
// foldersToHandle returns the list of folders needing a summary update, and
|
||||||
// clears the list.
|
// clears the list.
|
||||||
func (c *folderSummarySvc) foldersToHandle() []string {
|
func (c *folderSummaryService) foldersToHandle() []string {
|
||||||
// We only recalculate summaries if someone is listening to events
|
// We only recalculate summaries if someone is listening to events
|
||||||
// (a request to /rest/events has been made within the last
|
// (a request to /rest/events has been made within the last
|
||||||
// pingEventInterval).
|
// pingEventInterval).
|
||||||
@ -162,7 +162,7 @@ func (c *folderSummarySvc) foldersToHandle() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sendSummary send the summary events for a single folder
|
// sendSummary send the summary events for a single folder
|
||||||
func (c *folderSummarySvc) sendSummary(folder string) {
|
func (c *folderSummaryService) sendSummary(folder string) {
|
||||||
// The folder summary contains how many bytes, files etc
|
// The folder summary contains how many bytes, files etc
|
||||||
// are in the folder and how in sync we are.
|
// are in the folder and how in sync we are.
|
||||||
data := folderSummary(c.cfg, c.model, folder)
|
data := folderSummary(c.cfg, c.model, folder)
|
||||||
@ -192,7 +192,7 @@ func (c *folderSummarySvc) sendSummary(folder string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *folderSummarySvc) gotEventRequest() {
|
func (c *folderSummaryService) gotEventRequest() {
|
||||||
c.lastEventReqMut.Lock()
|
c.lastEventReqMut.Lock()
|
||||||
c.lastEventReq = time.Now()
|
c.lastEventReq = time.Now()
|
||||||
c.lastEventReqMut.Unlock()
|
c.lastEventReqMut.Unlock()
|
||||||
@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
// The UPnP service runs a loop for discovery of IGDs (Internet Gateway
|
// The UPnP service runs a loop for discovery of IGDs (Internet Gateway
|
||||||
// Devices) and setup/renewal of a port mapping.
|
// Devices) and setup/renewal of a port mapping.
|
||||||
type upnpSvc struct {
|
type upnpService struct {
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
localPort int
|
localPort int
|
||||||
extPort int
|
extPort int
|
||||||
@ -26,15 +26,15 @@ type upnpSvc struct {
|
|||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUPnPSvc(cfg *config.Wrapper, localPort int) *upnpSvc {
|
func newUPnPService(cfg *config.Wrapper, localPort int) *upnpService {
|
||||||
return &upnpSvc{
|
return &upnpService{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
localPort: localPort,
|
localPort: localPort,
|
||||||
extPortMut: sync.NewMutex(),
|
extPortMut: sync.NewMutex(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *upnpSvc) Serve() {
|
func (s *upnpService) Serve() {
|
||||||
foundIGD := true
|
foundIGD := true
|
||||||
s.stop = make(chan struct{})
|
s.stop = make(chan struct{})
|
||||||
|
|
||||||
@ -72,18 +72,18 @@ func (s *upnpSvc) Serve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *upnpSvc) Stop() {
|
func (s *upnpService) Stop() {
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *upnpSvc) ExternalPort() int {
|
func (s *upnpService) ExternalPort() int {
|
||||||
s.extPortMut.Lock()
|
s.extPortMut.Lock()
|
||||||
port := s.extPort
|
port := s.extPort
|
||||||
s.extPortMut.Unlock()
|
s.extPortMut.Unlock()
|
||||||
return port
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *upnpSvc) tryIGDs(igds []upnp.IGD, prevExtPort int) int {
|
func (s *upnpService) tryIGDs(igds []upnp.IGD, prevExtPort int) int {
|
||||||
// Lets try all the IGDs we found and use the first one that works.
|
// Lets try all the IGDs we found and use the first one that works.
|
||||||
// TODO: Use all of them, and sort out the resulting mess to the
|
// TODO: Use all of them, and sort out the resulting mess to the
|
||||||
// discovery announcement code...
|
// discovery announcement code...
|
||||||
@ -105,7 +105,7 @@ func (s *upnpSvc) tryIGDs(igds []upnp.IGD, prevExtPort int) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *upnpSvc) tryIGD(igd upnp.IGD, suggestedPort int) (int, error) {
|
func (s *upnpService) tryIGD(igd upnp.IGD, suggestedPort int) (int, error) {
|
||||||
var err error
|
var err error
|
||||||
leaseTime := s.cfg.Options().UPnPLeaseM * 60
|
leaseTime := s.cfg.Options().UPnPLeaseM * 60
|
||||||
|
|
||||||
@ -60,9 +60,9 @@ func (m *usageReportingManager) VerifyConfiguration(from, to config.Configuratio
|
|||||||
func (m *usageReportingManager) CommitConfiguration(from, to config.Configuration) bool {
|
func (m *usageReportingManager) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
if to.Options.URAccepted >= usageReportVersion && m.sup == nil {
|
if to.Options.URAccepted >= usageReportVersion && m.sup == nil {
|
||||||
// Usage reporting was turned on; lets start it.
|
// Usage reporting was turned on; lets start it.
|
||||||
svc := newUsageReportingService(m.cfg, m.model)
|
service := newUsageReportingService(m.cfg, m.model)
|
||||||
m.sup = suture.NewSimple("usageReporting")
|
m.sup = suture.NewSimple("usageReporting")
|
||||||
m.sup.Add(svc)
|
m.sup.Add(service)
|
||||||
m.sup.ServeBackground()
|
m.sup.ServeBackground()
|
||||||
} else if to.Options.URAccepted < usageReportVersion && m.sup != nil {
|
} else if to.Options.URAccepted < usageReportVersion && m.sup != nil {
|
||||||
// Usage reporting was turned off
|
// Usage reporting was turned off
|
||||||
@ -78,7 +78,7 @@ func (m *usageReportingManager) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reportData returns the data to be sent in a usage report. It's used in
|
// reportData returns the data to be sent in a usage report. It's used in
|
||||||
// various places, so not part of the usageReportingSvc object.
|
// various places, so not part of the usageReportingManager object.
|
||||||
func reportData(cfg *config.Wrapper, m *model.Model) map[string]interface{} {
|
func reportData(cfg *config.Wrapper, m *model.Model) map[string]interface{} {
|
||||||
res := make(map[string]interface{})
|
res := make(map[string]interface{})
|
||||||
res["urVersion"] = usageReportVersion
|
res["urVersion"] = usageReportVersion
|
||||||
|
|||||||
@ -15,20 +15,20 @@ import (
|
|||||||
|
|
||||||
// The verbose logging service subscribes to events and prints these in
|
// The verbose logging service subscribes to events and prints these in
|
||||||
// verbose format to the console using INFO level.
|
// verbose format to the console using INFO level.
|
||||||
type verboseSvc struct {
|
type verboseService struct {
|
||||||
stop chan struct{} // signals time to stop
|
stop chan struct{} // signals time to stop
|
||||||
started chan struct{} // signals startup complete
|
started chan struct{} // signals startup complete
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVerboseSvc() *verboseSvc {
|
func newVerboseService() *verboseService {
|
||||||
return &verboseSvc{
|
return &verboseService{
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
started: make(chan struct{}),
|
started: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve runs the verbose logging service.
|
// Serve runs the verbose logging service.
|
||||||
func (s *verboseSvc) Serve() {
|
func (s *verboseService) Serve() {
|
||||||
sub := events.Default.Subscribe(events.AllEvents)
|
sub := events.Default.Subscribe(events.AllEvents)
|
||||||
defer events.Default.Unsubscribe(sub)
|
defer events.Default.Unsubscribe(sub)
|
||||||
|
|
||||||
@ -55,17 +55,17 @@ func (s *verboseSvc) Serve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the verbose logging service.
|
// Stop stops the verbose logging service.
|
||||||
func (s *verboseSvc) Stop() {
|
func (s *verboseService) Stop() {
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForStart returns once the verbose logging service is ready to receive
|
// WaitForStart returns once the verbose logging service is ready to receive
|
||||||
// events, or immediately if it's already running.
|
// events, or immediately if it's already running.
|
||||||
func (s *verboseSvc) WaitForStart() {
|
func (s *verboseService) WaitForStart() {
|
||||||
<-s.started
|
<-s.started
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *verboseSvc) formatEvent(ev events.Event) string {
|
func (s *verboseService) formatEvent(ev events.Event) string {
|
||||||
switch ev.Type {
|
switch ev.Type {
|
||||||
case events.Ping, events.DownloadProgress, events.LocalIndexUpdated:
|
case events.Ping, events.DownloadProgress, events.LocalIndexUpdated:
|
||||||
// Skip
|
// Skip
|
||||||
@ -42,9 +42,9 @@ type Model interface {
|
|||||||
IsPaused(remoteID protocol.DeviceID) bool
|
IsPaused(remoteID protocol.DeviceID) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// The connection service listens on TLS and dials configured unconnected
|
// The connection connectionService listens on TLS and dials configured unconnected
|
||||||
// devices. Successful connections are handed to the model.
|
// devices. Successful connections are handed to the model.
|
||||||
type connectionSvc struct {
|
type connectionService struct {
|
||||||
*suture.Supervisor
|
*suture.Supervisor
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
myID protocol.DeviceID
|
myID protocol.DeviceID
|
||||||
@ -52,7 +52,7 @@ type connectionSvc struct {
|
|||||||
tlsCfg *tls.Config
|
tlsCfg *tls.Config
|
||||||
discoverer discover.Finder
|
discoverer discover.Finder
|
||||||
conns chan model.IntermediateConnection
|
conns chan model.IntermediateConnection
|
||||||
relaySvc *relay.Svc
|
relayService *relay.Service
|
||||||
bepProtocolName string
|
bepProtocolName string
|
||||||
tlsDefaultCommonName string
|
tlsDefaultCommonName string
|
||||||
lans []*net.IPNet
|
lans []*net.IPNet
|
||||||
@ -66,16 +66,16 @@ type connectionSvc struct {
|
|||||||
relaysEnabled bool
|
relaysEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnectionSvc(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, relaySvc *relay.Svc,
|
func NewConnectionService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, relayService *relay.Service,
|
||||||
bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) suture.Service {
|
bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) suture.Service {
|
||||||
svc := &connectionSvc{
|
service := &connectionService{
|
||||||
Supervisor: suture.NewSimple("connectionSvc"),
|
Supervisor: suture.NewSimple("connectionService"),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
myID: myID,
|
myID: myID,
|
||||||
model: mdl,
|
model: mdl,
|
||||||
tlsCfg: tlsCfg,
|
tlsCfg: tlsCfg,
|
||||||
discoverer: discoverer,
|
discoverer: discoverer,
|
||||||
relaySvc: relaySvc,
|
relayService: relayService,
|
||||||
conns: make(chan model.IntermediateConnection),
|
conns: make(chan model.IntermediateConnection),
|
||||||
bepProtocolName: bepProtocolName,
|
bepProtocolName: bepProtocolName,
|
||||||
tlsDefaultCommonName: tlsDefaultCommonName,
|
tlsDefaultCommonName: tlsDefaultCommonName,
|
||||||
@ -85,20 +85,20 @@ func NewConnectionSvc(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tl
|
|||||||
relaysEnabled: cfg.Options().RelaysEnabled,
|
relaysEnabled: cfg.Options().RelaysEnabled,
|
||||||
lastRelayCheck: make(map[protocol.DeviceID]time.Time),
|
lastRelayCheck: make(map[protocol.DeviceID]time.Time),
|
||||||
}
|
}
|
||||||
cfg.Subscribe(svc)
|
cfg.Subscribe(service)
|
||||||
|
|
||||||
if svc.cfg.Options().MaxSendKbps > 0 {
|
if service.cfg.Options().MaxSendKbps > 0 {
|
||||||
svc.writeRateLimit = ratelimit.NewBucketWithRate(float64(1000*svc.cfg.Options().MaxSendKbps), int64(5*1000*svc.cfg.Options().MaxSendKbps))
|
service.writeRateLimit = ratelimit.NewBucketWithRate(float64(1000*service.cfg.Options().MaxSendKbps), int64(5*1000*service.cfg.Options().MaxSendKbps))
|
||||||
}
|
}
|
||||||
if svc.cfg.Options().MaxRecvKbps > 0 {
|
if service.cfg.Options().MaxRecvKbps > 0 {
|
||||||
svc.readRateLimit = ratelimit.NewBucketWithRate(float64(1000*svc.cfg.Options().MaxRecvKbps), int64(5*1000*svc.cfg.Options().MaxRecvKbps))
|
service.readRateLimit = ratelimit.NewBucketWithRate(float64(1000*service.cfg.Options().MaxRecvKbps), int64(5*1000*service.cfg.Options().MaxRecvKbps))
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are several moving parts here; one routine per listening address
|
// There are several moving parts here; one routine per listening address
|
||||||
// to handle incoming connections, one routine to periodically attempt
|
// to handle incoming connections, one routine to periodically attempt
|
||||||
// outgoing connections, one routine to the the common handling
|
// outgoing connections, one routine to the the common handling
|
||||||
// regardless of whether the connection was incoming or outgoing.
|
// regardless of whether the connection was incoming or outgoing.
|
||||||
// Furthermore, a relay service which handles incoming requests to connect
|
// Furthermore, a relay connectionService which handles incoming requests to connect
|
||||||
// via the relays.
|
// via the relays.
|
||||||
//
|
//
|
||||||
// TODO: Clean shutdown, and/or handling config changes on the fly. We
|
// TODO: Clean shutdown, and/or handling config changes on the fly. We
|
||||||
@ -106,8 +106,8 @@ func NewConnectionSvc(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tl
|
|||||||
// not new listen addresses and we don't support disconnecting devices
|
// not new listen addresses and we don't support disconnecting devices
|
||||||
// that are removed and so on...
|
// that are removed and so on...
|
||||||
|
|
||||||
svc.Add(serviceFunc(svc.connect))
|
service.Add(serviceFunc(service.connect))
|
||||||
for _, addr := range svc.cfg.Options().ListenAddress {
|
for _, addr := range service.cfg.Options().ListenAddress {
|
||||||
uri, err := url.Parse(addr)
|
uri, err := url.Parse(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Failed to parse listen address:", addr, err)
|
l.Infoln("Failed to parse listen address:", addr, err)
|
||||||
@ -122,20 +122,20 @@ func NewConnectionSvc(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tl
|
|||||||
|
|
||||||
l.Debugln("listening on", uri)
|
l.Debugln("listening on", uri)
|
||||||
|
|
||||||
svc.Add(serviceFunc(func() {
|
service.Add(serviceFunc(func() {
|
||||||
listener(uri, svc.tlsCfg, svc.conns)
|
listener(uri, service.tlsCfg, service.conns)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
svc.Add(serviceFunc(svc.handle))
|
service.Add(serviceFunc(service.handle))
|
||||||
|
|
||||||
if svc.relaySvc != nil {
|
if service.relayService != nil {
|
||||||
svc.Add(serviceFunc(svc.acceptRelayConns))
|
service.Add(serviceFunc(service.acceptRelayConns))
|
||||||
}
|
}
|
||||||
|
|
||||||
return svc
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) handle() {
|
func (s *connectionService) handle() {
|
||||||
next:
|
next:
|
||||||
for c := range s.conns {
|
for c := range s.conns {
|
||||||
cs := c.Conn.ConnectionState()
|
cs := c.Conn.ConnectionState()
|
||||||
@ -257,7 +257,7 @@ next:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) connect() {
|
func (s *connectionService) connect() {
|
||||||
delay := time.Second
|
delay := time.Second
|
||||||
for {
|
for {
|
||||||
l.Debugln("Reconnect loop")
|
l.Debugln("Reconnect loop")
|
||||||
@ -340,7 +340,7 @@ func (s *connectionSvc) connect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) resolveAddresses(deviceID protocol.DeviceID, inAddrs []string) (addrs []string, relays []discover.Relay) {
|
func (s *connectionService) resolveAddresses(deviceID protocol.DeviceID, inAddrs []string) (addrs []string, relays []discover.Relay) {
|
||||||
for _, addr := range inAddrs {
|
for _, addr := range inAddrs {
|
||||||
if addr == "dynamic" {
|
if addr == "dynamic" {
|
||||||
if s.discoverer != nil {
|
if s.discoverer != nil {
|
||||||
@ -356,7 +356,7 @@ func (s *connectionSvc) resolveAddresses(deviceID protocol.DeviceID, inAddrs []s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) connectDirect(deviceID protocol.DeviceID, addr string) *tls.Conn {
|
func (s *connectionService) connectDirect(deviceID protocol.DeviceID, addr string) *tls.Conn {
|
||||||
uri, err := url.Parse(addr)
|
uri, err := url.Parse(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Failed to parse connection url:", addr, err)
|
l.Infoln("Failed to parse connection url:", addr, err)
|
||||||
@ -379,7 +379,7 @@ func (s *connectionSvc) connectDirect(deviceID protocol.DeviceID, addr string) *
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) connectViaRelay(deviceID protocol.DeviceID, addr discover.Relay) *tls.Conn {
|
func (s *connectionService) connectViaRelay(deviceID protocol.DeviceID, addr discover.Relay) *tls.Conn {
|
||||||
uri, err := url.Parse(addr.URL)
|
uri, err := url.Parse(addr.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Failed to parse relay connection url:", addr, err)
|
l.Infoln("Failed to parse relay connection url:", addr, err)
|
||||||
@ -418,9 +418,9 @@ func (s *connectionSvc) connectViaRelay(deviceID protocol.DeviceID, addr discove
|
|||||||
return tc
|
return tc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) acceptRelayConns() {
|
func (s *connectionService) acceptRelayConns() {
|
||||||
for {
|
for {
|
||||||
conn := s.relaySvc.Accept()
|
conn := s.relayService.Accept()
|
||||||
s.conns <- model.IntermediateConnection{
|
s.conns <- model.IntermediateConnection{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
Type: model.ConnectionTypeRelayAccept,
|
Type: model.ConnectionTypeRelayAccept,
|
||||||
@ -428,7 +428,7 @@ func (s *connectionSvc) acceptRelayConns() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) shouldLimit(addr net.Addr) bool {
|
func (s *connectionService) shouldLimit(addr net.Addr) bool {
|
||||||
if s.cfg.Options().LimitBandwidthInLan {
|
if s.cfg.Options().LimitBandwidthInLan {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -445,11 +445,11 @@ func (s *connectionSvc) shouldLimit(addr net.Addr) bool {
|
|||||||
return !tcpaddr.IP.IsLoopback()
|
return !tcpaddr.IP.IsLoopback()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) VerifyConfiguration(from, to config.Configuration) error {
|
func (s *connectionService) VerifyConfiguration(from, to config.Configuration) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionSvc) CommitConfiguration(from, to config.Configuration) bool {
|
func (s *connectionService) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
s.mut.Lock()
|
s.mut.Lock()
|
||||||
s.relaysEnabled = to.Options.RelaysEnabled
|
s.relaysEnabled = to.Options.RelaysEnabled
|
||||||
s.mut.Unlock()
|
s.mut.Unlock()
|
||||||
|
|||||||
@ -65,8 +65,8 @@ func (m *CachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, p
|
|||||||
m.caches = append(m.caches, newCache())
|
m.caches = append(m.caches, newCache())
|
||||||
m.mut.Unlock()
|
m.mut.Unlock()
|
||||||
|
|
||||||
if svc, ok := finder.(suture.Service); ok {
|
if service, ok := finder.(suture.Service); ok {
|
||||||
m.Supervisor.Add(svc)
|
m.Supervisor.Add(service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ const (
|
|||||||
eventBroadcasterCheckInterval = 10 * time.Second
|
eventBroadcasterCheckInterval = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type Svc struct {
|
type Service struct {
|
||||||
*suture.Supervisor
|
*suture.Supervisor
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
tlsCfg *tls.Config
|
tlsCfg *tls.Config
|
||||||
@ -38,11 +38,11 @@ type Svc struct {
|
|||||||
conns chan *tls.Conn
|
conns chan *tls.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSvc(cfg *config.Wrapper, tlsCfg *tls.Config) *Svc {
|
func NewService(cfg *config.Wrapper, tlsCfg *tls.Config) *Service {
|
||||||
conns := make(chan *tls.Conn)
|
conns := make(chan *tls.Conn)
|
||||||
|
|
||||||
svc := &Svc{
|
service := &Service{
|
||||||
Supervisor: suture.New("Svc", suture.Spec{
|
Supervisor: suture.New("Service", suture.Spec{
|
||||||
Log: func(log string) {
|
Log: func(log string) {
|
||||||
l.Debugln(log)
|
l.Debugln(log)
|
||||||
},
|
},
|
||||||
@ -61,28 +61,28 @@ func NewSvc(cfg *config.Wrapper, tlsCfg *tls.Config) *Svc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rcfg := cfg.Raw()
|
rcfg := cfg.Raw()
|
||||||
svc.CommitConfiguration(rcfg, rcfg)
|
service.CommitConfiguration(rcfg, rcfg)
|
||||||
cfg.Subscribe(svc)
|
cfg.Subscribe(service)
|
||||||
|
|
||||||
receiver := &invitationReceiver{
|
receiver := &invitationReceiver{
|
||||||
tlsCfg: tlsCfg,
|
tlsCfg: tlsCfg,
|
||||||
conns: conns,
|
conns: conns,
|
||||||
invitations: svc.invitations,
|
invitations: service.invitations,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBc := &eventBroadcaster{
|
eventBc := &eventBroadcaster{
|
||||||
svc: svc,
|
Service: service,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.Add(receiver)
|
service.Add(receiver)
|
||||||
svc.Add(eventBc)
|
service.Add(eventBc)
|
||||||
|
|
||||||
return svc
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Svc) VerifyConfiguration(from, to config.Configuration) error {
|
func (s *Service) VerifyConfiguration(from, to config.Configuration) error {
|
||||||
for _, addr := range to.Options.RelayServers {
|
for _, addr := range to.Options.RelayServers {
|
||||||
_, err := url.Parse(addr)
|
_, err := url.Parse(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +92,7 @@ func (s *Svc) VerifyConfiguration(from, to config.Configuration) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Svc) CommitConfiguration(from, to config.Configuration) bool {
|
func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
existing := make(map[string]*url.URL, len(to.Options.RelayServers))
|
existing := make(map[string]*url.URL, len(to.Options.RelayServers))
|
||||||
|
|
||||||
for _, addr := range to.Options.RelayServers {
|
for _, addr := range to.Options.RelayServers {
|
||||||
@ -142,7 +142,7 @@ type Status struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Relays return the list of relays that currently have an OK status.
|
// Relays return the list of relays that currently have an OK status.
|
||||||
func (s *Svc) Relays() []string {
|
func (s *Service) Relays() []string {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
// A nil client does not have a status, really. Yet we may be called
|
// A nil client does not have a status, really. Yet we may be called
|
||||||
// this way, for raisins...
|
// this way, for raisins...
|
||||||
@ -162,7 +162,7 @@ func (s *Svc) Relays() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RelayStatus returns the latency and OK status for a given relay.
|
// RelayStatus returns the latency and OK status for a given relay.
|
||||||
func (s *Svc) RelayStatus(uri string) (time.Duration, bool) {
|
func (s *Service) RelayStatus(uri string) (time.Duration, bool) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
// A nil client does not have a status, really. Yet we may be called
|
// A nil client does not have a status, really. Yet we may be called
|
||||||
// this way, for raisins...
|
// this way, for raisins...
|
||||||
@ -182,7 +182,7 @@ func (s *Svc) RelayStatus(uri string) (time.Duration, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Accept returns a new *tls.Conn. The connection is already handshaken.
|
// Accept returns a new *tls.Conn. The connection is already handshaken.
|
||||||
func (s *Svc) Accept() *tls.Conn {
|
func (s *Service) Accept() *tls.Conn {
|
||||||
return <-s.conns
|
return <-s.conns
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +234,8 @@ func (r *invitationReceiver) Stop() {
|
|||||||
// no way to get the event feed directly from the relay lib. This may be
|
// no way to get the event feed directly from the relay lib. This may be
|
||||||
// something to revisit later, possibly.
|
// something to revisit later, possibly.
|
||||||
type eventBroadcaster struct {
|
type eventBroadcaster struct {
|
||||||
svc *Svc
|
Service *Service
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *eventBroadcaster) Serve() {
|
func (e *eventBroadcaster) Serve() {
|
||||||
@ -247,7 +247,7 @@ func (e *eventBroadcaster) Serve() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
curOKRelays := e.svc.Relays()
|
curOKRelays := e.Service.Relays()
|
||||||
|
|
||||||
changed := len(curOKRelays) != len(prevOKRelays)
|
changed := len(curOKRelays) != len(prevOKRelays)
|
||||||
if !changed {
|
if !changed {
|
||||||
|
|||||||
@ -58,13 +58,9 @@ func (n *IGD) URL() *url.URL {
|
|||||||
|
|
||||||
// An IGDService is a specific service provided by an IGD.
|
// An IGDService is a specific service provided by an IGD.
|
||||||
type IGDService struct {
|
type IGDService struct {
|
||||||
serviceID string
|
ID string
|
||||||
serviceURL string
|
URL string
|
||||||
serviceURN string
|
URN string
|
||||||
}
|
|
||||||
|
|
||||||
func (s *IGDService) ID() string {
|
|
||||||
return s.serviceID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Protocol string
|
type Protocol string
|
||||||
@ -75,9 +71,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type upnpService struct {
|
type upnpService struct {
|
||||||
ServiceID string `xml:"serviceId"`
|
ID string `xml:"serviceId"`
|
||||||
ServiceType string `xml:"serviceType"`
|
Type string `xml:"serviceType"`
|
||||||
ControlURL string `xml:"controlURL"`
|
ControlURL string `xml:"controlURL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type upnpDevice struct {
|
type upnpDevice struct {
|
||||||
@ -132,8 +128,8 @@ nextResult:
|
|||||||
if existingResult.uuid == result.uuid {
|
if existingResult.uuid == result.uuid {
|
||||||
if shouldDebug() {
|
if shouldDebug() {
|
||||||
l.Debugf("Skipping duplicate result %s with services:", result.uuid)
|
l.Debugf("Skipping duplicate result %s with services:", result.uuid)
|
||||||
for _, svc := range result.services {
|
for _, service := range result.services {
|
||||||
l.Debugf("* [%s] %s", svc.serviceID, svc.serviceURL)
|
l.Debugf("* [%s] %s", service.ID, service.URL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue nextResult
|
continue nextResult
|
||||||
@ -143,8 +139,8 @@ nextResult:
|
|||||||
results = append(results, result)
|
results = append(results, result)
|
||||||
if shouldDebug() {
|
if shouldDebug() {
|
||||||
l.Debugf("UPnP discovery result %s with services:", result.uuid)
|
l.Debugf("UPnP discovery result %s with services:", result.uuid)
|
||||||
for _, svc := range result.services {
|
for _, service := range result.services {
|
||||||
l.Debugf("* [%s] %s", svc.serviceID, svc.serviceURL)
|
l.Debugf("* [%s] %s", service.ID, service.URL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,9 +313,9 @@ func getChildDevices(d upnpDevice, deviceType string) []upnpDevice {
|
|||||||
|
|
||||||
func getChildServices(d upnpDevice, serviceType string) []upnpService {
|
func getChildServices(d upnpDevice, serviceType string) []upnpService {
|
||||||
var result []upnpService
|
var result []upnpService
|
||||||
for _, svc := range d.Services {
|
for _, service := range d.Services {
|
||||||
if svc.ServiceType == serviceType {
|
if service.Type == serviceType {
|
||||||
result = append(result, svc)
|
result = append(result, service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@ -352,7 +348,7 @@ func getServiceDescriptions(rootURL string, device upnpDevice) ([]IGDService, er
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIGDServices(rootURL string, device upnpDevice, wanDeviceURN string, wanConnectionURN string, serviceURNs []string) []IGDService {
|
func getIGDServices(rootURL string, device upnpDevice, wanDeviceURN string, wanConnectionURN string, URNs []string) []IGDService {
|
||||||
var result []IGDService
|
var result []IGDService
|
||||||
|
|
||||||
devices := getChildDevices(device, wanDeviceURN)
|
devices := getChildDevices(device, wanDeviceURN)
|
||||||
@ -370,21 +366,21 @@ func getIGDServices(rootURL string, device upnpDevice, wanDeviceURN string, wanC
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, connection := range connections {
|
for _, connection := range connections {
|
||||||
for _, serviceURN := range serviceURNs {
|
for _, URN := range URNs {
|
||||||
services := getChildServices(connection, serviceURN)
|
services := getChildServices(connection, URN)
|
||||||
|
|
||||||
l.Debugln(rootURL, "- no services of type", serviceURN, " found on connection.")
|
l.Debugln(rootURL, "- no services of type", URN, " found on connection.")
|
||||||
|
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
if len(service.ControlURL) == 0 {
|
if len(service.ControlURL) == 0 {
|
||||||
l.Infoln(rootURL+"- malformed", service.ServiceType, "description: no control URL.")
|
l.Infoln(rootURL+"- malformed", service.Type, "description: no control URL.")
|
||||||
} else {
|
} else {
|
||||||
u, _ := url.Parse(rootURL)
|
u, _ := url.Parse(rootURL)
|
||||||
replaceRawPath(u, service.ControlURL)
|
replaceRawPath(u, service.ControlURL)
|
||||||
|
|
||||||
l.Debugln(rootURL, "- found", service.ServiceType, "with URL", u)
|
l.Debugln(rootURL, "- found", service.Type, "with URL", u)
|
||||||
|
|
||||||
service := IGDService{serviceID: service.ServiceID, serviceURL: u.String(), serviceURN: service.ServiceType}
|
service := IGDService{ID: service.ID, URL: u.String(), URN: service.Type}
|
||||||
|
|
||||||
result = append(result, service)
|
result = append(result, service)
|
||||||
}
|
}
|
||||||
@ -525,9 +521,9 @@ func (s *IGDService) AddPortMapping(localIPAddress string, protocol Protocol, ex
|
|||||||
<NewPortMappingDescription>%s</NewPortMappingDescription>
|
<NewPortMappingDescription>%s</NewPortMappingDescription>
|
||||||
<NewLeaseDuration>%d</NewLeaseDuration>
|
<NewLeaseDuration>%d</NewLeaseDuration>
|
||||||
</u:AddPortMapping>`
|
</u:AddPortMapping>`
|
||||||
body := fmt.Sprintf(tpl, s.serviceURN, externalPort, protocol, internalPort, localIPAddress, description, timeout)
|
body := fmt.Sprintf(tpl, s.URN, externalPort, protocol, internalPort, localIPAddress, description, timeout)
|
||||||
|
|
||||||
response, err := soapRequest(s.serviceURL, s.serviceURN, "AddPortMapping", body)
|
response, err := soapRequest(s.URL, s.URN, "AddPortMapping", body)
|
||||||
if err != nil && timeout > 0 {
|
if err != nil && timeout > 0 {
|
||||||
// Try to repair error code 725 - OnlyPermanentLeasesSupported
|
// Try to repair error code 725 - OnlyPermanentLeasesSupported
|
||||||
envelope := &soapErrorResponse{}
|
envelope := &soapErrorResponse{}
|
||||||
@ -549,9 +545,9 @@ func (s *IGDService) DeletePortMapping(protocol Protocol, externalPort int) erro
|
|||||||
<NewExternalPort>%d</NewExternalPort>
|
<NewExternalPort>%d</NewExternalPort>
|
||||||
<NewProtocol>%s</NewProtocol>
|
<NewProtocol>%s</NewProtocol>
|
||||||
</u:DeletePortMapping>`
|
</u:DeletePortMapping>`
|
||||||
body := fmt.Sprintf(tpl, s.serviceURN, externalPort, protocol)
|
body := fmt.Sprintf(tpl, s.URN, externalPort, protocol)
|
||||||
|
|
||||||
_, err := soapRequest(s.serviceURL, s.serviceURN, "DeletePortMapping", body)
|
_, err := soapRequest(s.URL, s.URN, "DeletePortMapping", body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -566,9 +562,9 @@ func (s *IGDService) DeletePortMapping(protocol Protocol, externalPort int) erro
|
|||||||
func (s *IGDService) GetExternalIPAddress() (net.IP, error) {
|
func (s *IGDService) GetExternalIPAddress() (net.IP, error) {
|
||||||
tpl := `<u:GetExternalIPAddress xmlns:u="%s" />`
|
tpl := `<u:GetExternalIPAddress xmlns:u="%s" />`
|
||||||
|
|
||||||
body := fmt.Sprintf(tpl, s.serviceURN)
|
body := fmt.Sprintf(tpl, s.URN)
|
||||||
|
|
||||||
response, err := soapRequest(s.serviceURL, s.serviceURN, "GetExternalIPAddress", body)
|
response, err := soapRequest(s.URL, s.URN, "GetExternalIPAddress", body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user