2015-03-25 07:16:52 +00:00
|
|
|
// Copyright (C) 2014-2015 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
2014-06-01 20:50:14 +00:00
|
|
|
|
2013-12-23 02:35:05 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-09-13 09:44:33 +00:00
|
|
|
"crypto/tls"
|
2015-03-25 07:16:52 +00:00
|
|
|
"database/sql"
|
2014-02-20 16:40:15 +00:00
|
|
|
"flag"
|
2016-06-02 11:58:39 +00:00
|
|
|
"fmt"
|
2013-12-23 02:35:05 +00:00
|
|
|
"log"
|
2014-02-20 16:40:15 +00:00
|
|
|
"os"
|
2016-06-02 11:58:39 +00:00
|
|
|
"runtime"
|
|
|
|
"strconv"
|
2014-02-17 08:23:37 +00:00
|
|
|
"time"
|
2013-12-23 02:35:05 +00:00
|
|
|
|
2015-11-04 16:55:21 +00:00
|
|
|
"github.com/syncthing/syncthing/lib/protocol"
|
2015-03-25 07:16:52 +00:00
|
|
|
"github.com/thejerf/suture"
|
2013-12-23 02:35:05 +00:00
|
|
|
)
|
|
|
|
|
2015-11-13 09:14:19 +00:00
|
|
|
const (
|
|
|
|
minNegCache = 60 // seconds
|
|
|
|
maxNegCache = 3600 // seconds
|
|
|
|
maxDeviceAge = 7 * 86400 // one week, in seconds
|
|
|
|
)
|
|
|
|
|
2016-06-02 11:58:39 +00:00
|
|
|
var (
|
|
|
|
Version string
|
|
|
|
BuildStamp string
|
|
|
|
BuildUser string
|
|
|
|
BuildHost string
|
|
|
|
|
|
|
|
BuildDate time.Time
|
|
|
|
LongVersion string
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
stamp, _ := strconv.Atoi(BuildStamp)
|
|
|
|
BuildDate = time.Unix(int64(stamp), 0)
|
|
|
|
|
|
|
|
date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
|
|
|
|
LongVersion = fmt.Sprintf(`discosrv %s (%s %s-%s) %s@%s %s`, Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildUser, BuildHost, date)
|
|
|
|
}
|
|
|
|
|
2013-12-23 02:35:05 +00:00
|
|
|
var (
|
2015-03-25 07:16:52 +00:00
|
|
|
lruSize = 10240
|
|
|
|
limitAvg = 5
|
|
|
|
limitBurst = 20
|
|
|
|
globalStats stats
|
2015-05-31 11:31:28 +00:00
|
|
|
statsFile string
|
2015-07-21 22:56:27 +00:00
|
|
|
backend = "ql"
|
|
|
|
dsn = getEnvDefault("DISCOSRV_DB_DSN", "memory://discosrv")
|
2015-09-13 09:44:33 +00:00
|
|
|
certFile = "cert.pem"
|
|
|
|
keyFile = "key.pem"
|
|
|
|
debug = false
|
2016-06-07 07:33:11 +00:00
|
|
|
useHTTP = false
|
2013-12-23 02:35:05 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2015-03-25 07:16:52 +00:00
|
|
|
const (
|
|
|
|
cleanIntv = 1 * time.Hour
|
|
|
|
statsIntv = 5 * time.Minute
|
|
|
|
)
|
|
|
|
|
2014-02-20 16:40:15 +00:00
|
|
|
var listen string
|
2015-03-25 07:16:52 +00:00
|
|
|
|
|
|
|
log.SetOutput(os.Stdout)
|
|
|
|
log.SetFlags(0)
|
2014-02-20 16:40:15 +00:00
|
|
|
|
2015-09-13 09:44:33 +00:00
|
|
|
flag.StringVar(&listen, "listen", ":8443", "Listen address")
|
2014-06-27 20:39:03 +00:00
|
|
|
flag.IntVar(&lruSize, "limit-cache", lruSize, "Limiter cache entries")
|
|
|
|
flag.IntVar(&limitAvg, "limit-avg", limitAvg, "Allowed average package rate, per 10 s")
|
|
|
|
flag.IntVar(&limitBurst, "limit-burst", limitBurst, "Allowed burst size, packets")
|
2015-05-31 11:31:28 +00:00
|
|
|
flag.StringVar(&statsFile, "stats-file", statsFile, "File to write periodic operation stats to")
|
2015-07-21 22:56:27 +00:00
|
|
|
flag.StringVar(&backend, "db-backend", backend, "Database backend to use")
|
|
|
|
flag.StringVar(&dsn, "db-dsn", dsn, "Database DSN")
|
2015-09-13 09:44:33 +00:00
|
|
|
flag.StringVar(&certFile, "cert", certFile, "Certificate file")
|
|
|
|
flag.StringVar(&keyFile, "key", keyFile, "Key file")
|
|
|
|
flag.BoolVar(&debug, "debug", debug, "Debug")
|
2016-06-07 07:33:11 +00:00
|
|
|
flag.BoolVar(&useHTTP, "http", useHTTP, "Listen on HTTP (behind an HTTPS proxy)")
|
2014-02-20 16:40:15 +00:00
|
|
|
flag.Parse()
|
|
|
|
|
2016-06-02 11:58:39 +00:00
|
|
|
log.Println(LongVersion)
|
|
|
|
|
2015-11-06 16:36:59 +00:00
|
|
|
var cert tls.Certificate
|
|
|
|
var err error
|
2016-06-07 07:33:11 +00:00
|
|
|
if !useHTTP {
|
2015-11-06 16:36:59 +00:00
|
|
|
cert, err = tls.LoadX509KeyPair(certFile, keyFile)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to load X509 key pair:", err)
|
|
|
|
}
|
2013-12-23 02:35:05 +00:00
|
|
|
|
2015-11-06 16:36:59 +00:00
|
|
|
devID := protocol.NewDeviceID(cert.Certificate[0])
|
|
|
|
log.Println("Server device ID is", devID)
|
|
|
|
}
|
2015-11-04 16:55:21 +00:00
|
|
|
|
2015-07-21 22:56:27 +00:00
|
|
|
db, err := sql.Open(backend, dsn)
|
2014-09-08 09:48:26 +00:00
|
|
|
if err != nil {
|
2015-07-21 22:56:27 +00:00
|
|
|
log.Fatalln("sql.Open:", err)
|
2014-09-08 09:48:26 +00:00
|
|
|
}
|
2015-07-21 22:56:27 +00:00
|
|
|
prep, err := setup(backend, db)
|
2014-09-08 09:48:26 +00:00
|
|
|
if err != nil {
|
2015-03-25 07:16:52 +00:00
|
|
|
log.Fatalln("Setup:", err)
|
2014-04-19 21:14:56 +00:00
|
|
|
}
|
2014-02-17 08:23:37 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
main := suture.NewSimple("main")
|
2014-04-03 21:38:32 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
main.Add(&querysrv{
|
2015-09-13 09:44:33 +00:00
|
|
|
addr: listen,
|
|
|
|
cert: cert,
|
2015-03-25 07:16:52 +00:00
|
|
|
db: db,
|
|
|
|
prep: prep,
|
|
|
|
})
|
2014-04-03 21:38:32 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
main.Add(&cleansrv{
|
|
|
|
intv: cleanIntv,
|
|
|
|
db: db,
|
|
|
|
prep: prep,
|
|
|
|
})
|
2014-04-03 21:38:32 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
main.Add(&statssrv{
|
|
|
|
intv: statsIntv,
|
2015-05-31 11:31:28 +00:00
|
|
|
file: statsFile,
|
|
|
|
db: db,
|
2015-03-25 07:16:52 +00:00
|
|
|
})
|
2013-12-23 02:35:05 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
globalStats.Reset()
|
|
|
|
main.Serve()
|
2014-04-03 20:44:40 +00:00
|
|
|
}
|
2014-02-20 16:40:15 +00:00
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
func getEnvDefault(key, def string) string {
|
|
|
|
if val := os.Getenv(key); val != "" {
|
|
|
|
return val
|
2014-06-29 23:42:03 +00:00
|
|
|
}
|
2015-03-25 07:16:52 +00:00
|
|
|
return def
|
2014-04-03 20:44:40 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 07:16:52 +00:00
|
|
|
func next(intv time.Duration) time.Duration {
|
2014-04-19 21:14:56 +00:00
|
|
|
t0 := time.Now()
|
2015-03-25 07:16:52 +00:00
|
|
|
t1 := t0.Add(intv).Truncate(intv)
|
|
|
|
return t1.Sub(t0)
|
2014-09-08 09:48:26 +00:00
|
|
|
}
|