mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-10 06:49:31 -05:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24b8f9211a | ||
|
|
ea0bed2238 | ||
|
|
e2fe57c440 | ||
|
|
434a0ccf2a | ||
|
|
e7bf3ac108 | ||
|
|
c5bdaebf2b |
@@ -1,4 +1,4 @@
|
||||
syncthing
|
||||
syncthing [](https://drone.io/github.com/calmh/syncthing/latest)
|
||||
=========
|
||||
|
||||
This is the `syncthing` project. The following are the project goals:
|
||||
|
||||
@@ -17,7 +17,7 @@ func Blocks(r io.Reader, blocksize int) ([]Block, error) {
|
||||
var blocks []Block
|
||||
var offset int64
|
||||
for {
|
||||
lr := &io.LimitedReader{r, int64(blocksize)}
|
||||
lr := &io.LimitedReader{R: r, N: int64(blocksize)}
|
||||
hf := sha256.New()
|
||||
n, err := io.Copy(hf, lr)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,7 +34,7 @@ type Discoverer struct {
|
||||
}
|
||||
|
||||
var (
|
||||
ErrIncorrectMagic = errors.New("Incorrect magic number")
|
||||
ErrIncorrectMagic = errors.New("incorrect magic number")
|
||||
)
|
||||
|
||||
// We tolerate a certain amount of errors because we might be running on
|
||||
@@ -91,7 +91,7 @@ func (d *Discoverer) sendAnnouncements() {
|
||||
}
|
||||
|
||||
if Debug {
|
||||
fmt.Println("send announcement -> ", remote)
|
||||
log.Println("send announcement -> ", remote)
|
||||
}
|
||||
_, _, err = d.conn.WriteMsgUDP(buf, nil, remote)
|
||||
if err != nil {
|
||||
@@ -123,7 +123,7 @@ func (d *Discoverer) sendExtAnnouncements() {
|
||||
|
||||
for errCounter < maxErrors {
|
||||
if Debug {
|
||||
fmt.Println("send announcement -> ", remote)
|
||||
log.Println("send announcement -> ", remote)
|
||||
}
|
||||
_, _, err = d.conn.WriteMsgUDP(buf, nil, remote)
|
||||
if err != nil {
|
||||
@@ -134,7 +134,7 @@ func (d *Discoverer) sendExtAnnouncements() {
|
||||
}
|
||||
time.Sleep(d.ExtBroadcastIntv)
|
||||
}
|
||||
log.Println("discover/write: %v: stopping due to too many errors:", remote, err)
|
||||
log.Printf("discover/write: %v: stopping due to too many errors: %v", remote, err)
|
||||
}
|
||||
|
||||
func (d *Discoverer) recvAnnouncements() {
|
||||
@@ -184,7 +184,6 @@ func (d *Discoverer) recvAnnouncements() {
|
||||
d.registryLock.Lock()
|
||||
_, seen := d.registry[pkt.NodeID]
|
||||
if !seen {
|
||||
fmt.Println("new node seen, forced announce")
|
||||
select {
|
||||
case d.forcedBroadcastTick <- time.Now():
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ func TestFileQueueThreadHandling(t *testing.T) {
|
||||
close(start)
|
||||
wg.Wait()
|
||||
if int(gotTot) != total {
|
||||
t.Error("Total mismatch; %d != %d", gotTot, total)
|
||||
t.Errorf("Total mismatch; %d != %d", gotTot, total)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,13 +283,13 @@ func TestDeleteAt(t *testing.T) {
|
||||
q.files = queuedFileList{{name: "a"}, {name: "b"}, {name: "c"}, {name: "d"}}
|
||||
q.deleteAt(i)
|
||||
if l := len(q.files); l != 3 {
|
||||
t.Fatal("deleteAt(%d) failed; %d != 3", i, l)
|
||||
t.Fatalf("deleteAt(%d) failed; %d != 3", i, l)
|
||||
}
|
||||
}
|
||||
|
||||
q.files = queuedFileList{{name: "a"}}
|
||||
q.deleteAt(0)
|
||||
if l := len(q.files); l != 0 {
|
||||
t.Fatal("deleteAt(only) failed; %d != 0", l)
|
||||
t.Fatalf("deleteAt(only) failed; %d != 0", l)
|
||||
}
|
||||
}
|
||||
|
||||
36
main.go
36
main.go
@@ -24,11 +24,10 @@ import (
|
||||
)
|
||||
|
||||
var cfg Configuration
|
||||
var Version string = "unknown-dev"
|
||||
var Version = "unknown-dev"
|
||||
|
||||
var (
|
||||
myID string
|
||||
config ini.Config
|
||||
myID string
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -83,7 +82,7 @@ func main() {
|
||||
fatalErr(err)
|
||||
}
|
||||
|
||||
myID = string(certId(cert.Certificate[0]))
|
||||
myID = string(certID(cert.Certificate[0]))
|
||||
log.SetPrefix("[" + myID[0:5] + "] ")
|
||||
logger.SetPrefix("[" + myID[0:5] + "] ")
|
||||
|
||||
@@ -188,16 +187,26 @@ func main() {
|
||||
|
||||
// GUI
|
||||
if cfg.Options.GUIEnabled && cfg.Options.GUIAddress != "" {
|
||||
host, port, err := net.SplitHostPort(cfg.Options.GUIAddress)
|
||||
addr, err := net.ResolveTCPAddr("tcp", cfg.Options.GUIAddress)
|
||||
if err != nil {
|
||||
warnf("Cannot start GUI on %q: %v", cfg.Options.GUIAddress, err)
|
||||
} else {
|
||||
if len(host) > 0 {
|
||||
infof("Starting web GUI on http://%s", cfg.Options.GUIAddress)
|
||||
} else {
|
||||
infof("Starting web GUI on port %s", port)
|
||||
var hostOpen, hostShow string
|
||||
switch {
|
||||
case addr.IP == nil:
|
||||
hostOpen = "localhost"
|
||||
hostShow = "0.0.0.0"
|
||||
case addr.IP.IsUnspecified():
|
||||
hostOpen = "localhost"
|
||||
hostShow = addr.IP.String()
|
||||
default:
|
||||
hostOpen = addr.IP.String()
|
||||
hostShow = hostOpen
|
||||
}
|
||||
|
||||
infof("Starting web GUI on http://%s:%d/", hostShow, addr.Port)
|
||||
startGUI(cfg.Options.GUIAddress, m)
|
||||
openURL(fmt.Sprintf("http://%s:%d", hostOpen, addr.Port))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +397,7 @@ listen:
|
||||
continue
|
||||
}
|
||||
|
||||
remoteID := certId(tc.ConnectionState().PeerCertificates[0].Raw)
|
||||
remoteID := certID(tc.ConnectionState().PeerCertificates[0].Raw)
|
||||
|
||||
if remoteID == myID {
|
||||
warnf("Connect from myself (%s) - should not happen", remoteID)
|
||||
@@ -469,7 +478,7 @@ func connect(myID string, disc *discover.Discoverer, m *Model, tlsCfg *tls.Confi
|
||||
continue
|
||||
}
|
||||
|
||||
remoteID := certId(conn.ConnectionState().PeerCertificates[0].Raw)
|
||||
remoteID := certID(conn.ConnectionState().PeerCertificates[0].Raw)
|
||||
if remoteID != nodeCfg.NodeID {
|
||||
warnln("Unexpected nodeID", remoteID, "!=", nodeCfg.NodeID)
|
||||
conn.Close()
|
||||
@@ -502,7 +511,10 @@ func saveIndex(m *Model) {
|
||||
|
||||
gzw := gzip.NewWriter(idxf)
|
||||
|
||||
protocol.IndexMessage{"local", m.ProtocolIndex()}.EncodeXDR(gzw)
|
||||
protocol.IndexMessage{
|
||||
Repository: "local",
|
||||
Files: m.ProtocolIndex(),
|
||||
}.EncodeXDR(gzw)
|
||||
gzw.Close()
|
||||
idxf.Close()
|
||||
os.Rename(fullName+".tmp", fullName)
|
||||
|
||||
3
model.go
3
model.go
@@ -64,9 +64,6 @@ type Connection interface {
|
||||
const (
|
||||
idxBcastHoldtime = 15 * time.Second // Wait at least this long after the last index modification
|
||||
idxBcastMaxDelay = 120 * time.Second // Unless we've already waited this long
|
||||
|
||||
minFileHoldTimeS = 60 // Never allow file changes more often than this
|
||||
maxFileHoldTimeS = 600 // Always allow file changes at least this often
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
34
openurl.go
Normal file
34
openurl.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func openURL(url string) error {
|
||||
if runtime.GOOS == "windows" {
|
||||
return exec.Command("cmd.exe", "/C", "start "+url).Run()
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
return exec.Command("open", url).Run()
|
||||
}
|
||||
|
||||
return exec.Command("xdg-open", url).Run()
|
||||
}
|
||||
@@ -46,7 +46,6 @@ func (e *ErrPipe) Write(data []byte) (int, error) {
|
||||
e.PipeWriter.CloseWithError(e.err)
|
||||
e.closed = true
|
||||
return n, e.err
|
||||
} else {
|
||||
return e.PipeWriter.Write(data)
|
||||
}
|
||||
return e.PipeWriter.Write(data)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrClusterHash = fmt.Errorf("Configuration error: mismatched cluster hash")
|
||||
ErrClusterHash = fmt.Errorf("configuration error: mismatched cluster hash")
|
||||
ErrClosed = errors.New("connection closed")
|
||||
)
|
||||
|
||||
type Model interface {
|
||||
@@ -56,7 +57,7 @@ type Connection struct {
|
||||
xw *xdr.Writer
|
||||
closed bool
|
||||
awaiting map[int]chan asyncResult
|
||||
nextId int
|
||||
nextID int
|
||||
indexSent map[string]map[string][2]int64
|
||||
peerOptions map[string]string
|
||||
myOptions map[string]string
|
||||
@@ -68,8 +69,6 @@ type Connection struct {
|
||||
statisticsLock sync.Mutex
|
||||
}
|
||||
|
||||
var ErrClosed = errors.New("Connection closed")
|
||||
|
||||
type asyncResult struct {
|
||||
val []byte
|
||||
err error
|
||||
@@ -105,7 +104,7 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
|
||||
c.myOptions = options
|
||||
go func() {
|
||||
c.Lock()
|
||||
header{0, c.nextId, messageTypeOptions}.encodeXDR(c.xw)
|
||||
header{0, c.nextID, messageTypeOptions}.encodeXDR(c.xw)
|
||||
var om OptionsMessage
|
||||
for k, v := range options {
|
||||
om.Options = append(om.Options, Option{k, v})
|
||||
@@ -118,7 +117,7 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
|
||||
if err != nil {
|
||||
log.Println("Warning: Write error during initial handshake:", err)
|
||||
}
|
||||
c.nextId++
|
||||
c.nextID++
|
||||
c.Unlock()
|
||||
}()
|
||||
}
|
||||
@@ -155,12 +154,12 @@ func (c *Connection) Index(repo string, idx []FileInfo) {
|
||||
idx = diff
|
||||
}
|
||||
|
||||
header{0, c.nextId, msgType}.encodeXDR(c.xw)
|
||||
header{0, c.nextID, msgType}.encodeXDR(c.xw)
|
||||
_, err := IndexMessage{repo, idx}.encodeXDR(c.xw)
|
||||
if err == nil {
|
||||
err = c.flush()
|
||||
}
|
||||
c.nextId = (c.nextId + 1) & 0xfff
|
||||
c.nextID = (c.nextID + 1) & 0xfff
|
||||
c.hasSentIndex = true
|
||||
c.Unlock()
|
||||
|
||||
@@ -178,8 +177,8 @@ func (c *Connection) Request(repo string, name string, offset int64, size int) (
|
||||
return nil, ErrClosed
|
||||
}
|
||||
rc := make(chan asyncResult)
|
||||
c.awaiting[c.nextId] = rc
|
||||
header{0, c.nextId, messageTypeRequest}.encodeXDR(c.xw)
|
||||
c.awaiting[c.nextID] = rc
|
||||
header{0, c.nextID, messageTypeRequest}.encodeXDR(c.xw)
|
||||
_, err := RequestMessage{repo, name, uint64(offset), uint32(size)}.encodeXDR(c.xw)
|
||||
if err == nil {
|
||||
err = c.flush()
|
||||
@@ -189,7 +188,7 @@ func (c *Connection) Request(repo string, name string, offset int64, size int) (
|
||||
c.close(err)
|
||||
return nil, err
|
||||
}
|
||||
c.nextId = (c.nextId + 1) & 0xfff
|
||||
c.nextID = (c.nextID + 1) & 0xfff
|
||||
c.Unlock()
|
||||
|
||||
res, ok := <-rc
|
||||
@@ -206,8 +205,8 @@ func (c *Connection) ping() bool {
|
||||
return false
|
||||
}
|
||||
rc := make(chan asyncResult, 1)
|
||||
c.awaiting[c.nextId] = rc
|
||||
header{0, c.nextId, messageTypePing}.encodeXDR(c.xw)
|
||||
c.awaiting[c.nextID] = rc
|
||||
header{0, c.nextID, messageTypePing}.encodeXDR(c.xw)
|
||||
err := c.flush()
|
||||
if err != nil {
|
||||
c.Unlock()
|
||||
@@ -218,7 +217,7 @@ func (c *Connection) ping() bool {
|
||||
c.close(c.xw.Error())
|
||||
return false
|
||||
}
|
||||
c.nextId = (c.nextId + 1) & 0xfff
|
||||
c.nextID = (c.nextID + 1) & 0xfff
|
||||
c.Unlock()
|
||||
|
||||
res, ok := <-rc
|
||||
@@ -268,7 +267,7 @@ loop:
|
||||
break loop
|
||||
}
|
||||
if hdr.version != 0 {
|
||||
c.close(fmt.Errorf("Protocol error: %s: unknown message version %#x", c.ID, hdr.version))
|
||||
c.close(fmt.Errorf("protocol error: %s: unknown message version %#x", c.id, hdr.version))
|
||||
break loop
|
||||
}
|
||||
|
||||
@@ -371,7 +370,7 @@ loop:
|
||||
}
|
||||
|
||||
default:
|
||||
c.close(fmt.Errorf("Protocol error: %s: unknown message type %#x", c.ID, hdr.msgType))
|
||||
c.close(fmt.Errorf("protocol error: %s: unknown message type %#x", c.id, hdr.msgType))
|
||||
break loop
|
||||
}
|
||||
}
|
||||
@@ -410,10 +409,10 @@ func (c *Connection) pingerLoop() {
|
||||
select {
|
||||
case ok := <-rc:
|
||||
if !ok {
|
||||
c.close(fmt.Errorf("Ping failure"))
|
||||
c.close(fmt.Errorf("ping failure"))
|
||||
}
|
||||
case <-time.After(pingTimeout):
|
||||
c.close(fmt.Errorf("Ping timeout"))
|
||||
c.close(fmt.Errorf("ping timeout"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestPing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPingErr(t *testing.T) {
|
||||
e := errors.New("Something broke")
|
||||
e := errors.New("something broke")
|
||||
|
||||
for i := 0; i < 12; i++ {
|
||||
for j := 0; j < 12; j++ {
|
||||
@@ -64,7 +64,7 @@ func TestPingErr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestResponseErr(t *testing.T) {
|
||||
e := errors.New("Something broke")
|
||||
e := errors.New("something broke")
|
||||
|
||||
var pass bool
|
||||
for i := 0; i < 48; i++ {
|
||||
@@ -99,16 +99,16 @@ func TestRequestResponseErr(t *testing.T) {
|
||||
t.Errorf("Incorrect response data %q", string(d))
|
||||
}
|
||||
if m0.repo != "default" {
|
||||
t.Error("Incorrect repo %q", m0.repo)
|
||||
t.Errorf("Incorrect repo %q", m0.repo)
|
||||
}
|
||||
if m0.name != "tn" {
|
||||
t.Error("Incorrect name %q", m0.name)
|
||||
t.Errorf("Incorrect name %q", m0.name)
|
||||
}
|
||||
if m0.offset != 1234 {
|
||||
t.Error("Incorrect offset %d", m0.offset)
|
||||
t.Errorf("Incorrect offset %d", m0.offset)
|
||||
}
|
||||
if m0.size != 5678 {
|
||||
t.Error("Incorrect size %d", m0.size)
|
||||
t.Errorf("Incorrect size %d", m0.size)
|
||||
}
|
||||
t.Logf("Pass at %d+%d bytes", i, j)
|
||||
pass = true
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_CHANGE_HISTORY = 4
|
||||
MaxChangeHistory = 4
|
||||
)
|
||||
|
||||
type change struct {
|
||||
@@ -45,8 +45,8 @@ func (h changeHistory) bandwidth(t time.Time) int64 {
|
||||
|
||||
func (h *changeHistory) append(size int64, t time.Time) {
|
||||
c := change{size, t}
|
||||
if len(h.changes) == MAX_CHANGE_HISTORY {
|
||||
h.changes = h.changes[1:MAX_CHANGE_HISTORY]
|
||||
if len(h.changes) == MaxChangeHistory {
|
||||
h.changes = h.changes[1:MaxChangeHistory]
|
||||
}
|
||||
h.changes = append(h.changes, c)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestSuppressor(t *testing.T) {
|
||||
// bw is 10000 / 10 = 1000
|
||||
t1 = t0.Add(10 * time.Second)
|
||||
if bw := s.changes["foo"].bandwidth(t1); bw != 1000 {
|
||||
t.Error("Incorrect bw %d", bw)
|
||||
t.Errorf("Incorrect bw %d", bw)
|
||||
}
|
||||
sup, prev = s.suppress("foo", 10000, t1)
|
||||
if sup {
|
||||
@@ -34,7 +34,7 @@ func TestSuppressor(t *testing.T) {
|
||||
// bw is (10000 + 10000) / 11 = 1818
|
||||
t1 = t0.Add(11 * time.Second)
|
||||
if bw := s.changes["foo"].bandwidth(t1); bw != 1818 {
|
||||
t.Error("Incorrect bw %d", bw)
|
||||
t.Errorf("Incorrect bw %d", bw)
|
||||
}
|
||||
sup, prev = s.suppress("foo", 100500, t1)
|
||||
if sup {
|
||||
@@ -47,7 +47,7 @@ func TestSuppressor(t *testing.T) {
|
||||
// bw is (10000 + 10000 + 100500) / 12 = 10041
|
||||
t1 = t0.Add(12 * time.Second)
|
||||
if bw := s.changes["foo"].bandwidth(t1); bw != 10041 {
|
||||
t.Error("Incorrect bw %d", bw)
|
||||
t.Errorf("Incorrect bw %d", bw)
|
||||
}
|
||||
sup, prev = s.suppress("foo", 10000000, t1) // value will be ignored
|
||||
if !sup {
|
||||
@@ -60,7 +60,7 @@ func TestSuppressor(t *testing.T) {
|
||||
// bw is (10000 + 10000 + 100500) / 15 = 8033
|
||||
t1 = t0.Add(15 * time.Second)
|
||||
if bw := s.changes["foo"].bandwidth(t1); bw != 8033 {
|
||||
t.Error("Incorrect bw %d", bw)
|
||||
t.Errorf("Incorrect bw %d", bw)
|
||||
}
|
||||
sup, prev = s.suppress("foo", 10000000, t1)
|
||||
if sup {
|
||||
@@ -84,29 +84,29 @@ func TestHistory(t *testing.T) {
|
||||
t.Errorf("Incorrect first record size %d", s)
|
||||
}
|
||||
|
||||
for i := 1; i < MAX_CHANGE_HISTORY; i++ {
|
||||
for i := 1; i < MaxChangeHistory; i++ {
|
||||
h.append(int64(40+i), t0.Add(time.Duration(i)*time.Second))
|
||||
}
|
||||
|
||||
if l := len(h.changes); l != MAX_CHANGE_HISTORY {
|
||||
if l := len(h.changes); l != MaxChangeHistory {
|
||||
t.Errorf("Incorrect history length %d", l)
|
||||
}
|
||||
if s := h.changes[0].size; s != 40 {
|
||||
t.Errorf("Incorrect first record size %d", s)
|
||||
}
|
||||
if s := h.changes[MAX_CHANGE_HISTORY-1].size; s != 40+MAX_CHANGE_HISTORY-1 {
|
||||
if s := h.changes[MaxChangeHistory-1].size; s != 40+MaxChangeHistory-1 {
|
||||
t.Errorf("Incorrect last record size %d", s)
|
||||
}
|
||||
|
||||
h.append(999, t0.Add(time.Duration(999)*time.Second))
|
||||
|
||||
if l := len(h.changes); l != MAX_CHANGE_HISTORY {
|
||||
if l := len(h.changes); l != MaxChangeHistory {
|
||||
t.Errorf("Incorrect history length %d", l)
|
||||
}
|
||||
if s := h.changes[0].size; s != 41 {
|
||||
t.Errorf("Incorrect first record size %d", s)
|
||||
}
|
||||
if s := h.changes[MAX_CHANGE_HISTORY-1].size; s != 999 {
|
||||
if s := h.changes[MaxChangeHistory-1].size; s != 999 {
|
||||
t.Errorf("Incorrect last record size %d", s)
|
||||
}
|
||||
|
||||
|
||||
2
tls.go
2
tls.go
@@ -25,7 +25,7 @@ func loadCert(dir string) (tls.Certificate, error) {
|
||||
return tls.LoadX509KeyPair(path.Join(dir, "cert.pem"), path.Join(dir, "key.pem"))
|
||||
}
|
||||
|
||||
func certId(bs []byte) string {
|
||||
func certID(bs []byte) string {
|
||||
hf := sha256.New()
|
||||
hf.Write(bs)
|
||||
id := hf.Sum(nil)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var ErrElementSizeExceeded = errors.New("Element size exceeded")
|
||||
var ErrElementSizeExceeded = errors.New("element size exceeded")
|
||||
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
|
||||
Reference in New Issue
Block a user