mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-13 00:58:32 +00:00
Update godeps, reduce amount of time spent testing a relay. Goddamit godeps.
This commit is contained in:
parent
845f31b98f
commit
f39f816a98
10
cmd/strelaypoolsrv/Godeps/Godeps.json
generated
10
cmd/strelaypoolsrv/Godeps/Godeps.json
generated
@ -29,27 +29,27 @@
|
|||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/protocol",
|
"ImportPath": "github.com/syncthing/syncthing/lib/protocol",
|
||||||
"Comment": "v0.12.0-beta1-119-g24c499d",
|
"Comment": "v0.12.0-beta1-119-g24c499d",
|
||||||
"Rev": "24c499d2822ae891c95406066456872e8d6c8164"
|
"Rev": "431d51f5c49ed7860e289ddab3c1fcf30004ff00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/relay/client",
|
"ImportPath": "github.com/syncthing/syncthing/lib/relay/client",
|
||||||
"Comment": "v0.12.0-beta1-119-g24c499d",
|
"Comment": "v0.12.0-beta1-119-g24c499d",
|
||||||
"Rev": "24c499d2822ae891c95406066456872e8d6c8164"
|
"Rev": "431d51f5c49ed7860e289ddab3c1fcf30004ff00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/relay/protocol",
|
"ImportPath": "github.com/syncthing/syncthing/lib/relay/protocol",
|
||||||
"Comment": "v0.12.0-beta1-119-g24c499d",
|
"Comment": "v0.12.0-beta1-119-g24c499d",
|
||||||
"Rev": "24c499d2822ae891c95406066456872e8d6c8164"
|
"Rev": "431d51f5c49ed7860e289ddab3c1fcf30004ff00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/sync",
|
"ImportPath": "github.com/syncthing/syncthing/lib/sync",
|
||||||
"Comment": "v0.12.0-beta1-119-g24c499d",
|
"Comment": "v0.12.0-beta1-119-g24c499d",
|
||||||
"Rev": "24c499d2822ae891c95406066456872e8d6c8164"
|
"Rev": "431d51f5c49ed7860e289ddab3c1fcf30004ff00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/tlsutil",
|
"ImportPath": "github.com/syncthing/syncthing/lib/tlsutil",
|
||||||
"Comment": "v0.12.0-beta1-119-g24c499d",
|
"Comment": "v0.12.0-beta1-119-g24c499d",
|
||||||
"Rev": "24c499d2822ae891c95406066456872e8d6c8164"
|
"Rev": "431d51f5c49ed7860e289ddab3c1fcf30004ff00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/text/transform",
|
"ImportPath": "golang.org/x/text/transform",
|
||||||
|
@ -6,10 +6,17 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/calmh/logger"
|
"github.com/syncthing/syncthing/lib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debug = strings.Contains(os.Getenv("STTRACE"), "protocol") || os.Getenv("STTRACE") == "all"
|
l = logger.DefaultLogger.NewFacility("protocol", "The BEP protocol")
|
||||||
l = logger.DefaultLogger
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
l.SetDebug("protocol", strings.Contains(os.Getenv("STTRACE"), "protocol") || os.Getenv("STTRACE") == "all")
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldDebug() bool {
|
||||||
|
return l.ShouldDebug("protocol")
|
||||||
|
}
|
||||||
|
@ -14,10 +14,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoError error = nil
|
ErrNoError error
|
||||||
ErrGeneric = errors.New("generic error")
|
ErrGeneric = errors.New("generic error")
|
||||||
ErrNoSuchFile = errors.New("no such file")
|
ErrNoSuchFile = errors.New("no such file")
|
||||||
ErrInvalid = errors.New("file is invalid")
|
ErrInvalid = errors.New("file is invalid")
|
||||||
)
|
)
|
||||||
|
|
||||||
var lookupError = map[int32]error{
|
var lookupError = map[int32]error{
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
// Copyright (C) 2014 The Protocol Authors.
|
// Copyright (C) 2014 The Protocol Authors.
|
||||||
|
|
||||||
//go:generate -command genxdr go run ../syncthing/Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
|
//go:generate -command genxdr go run ../../Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
|
||||||
//go:generate genxdr -o message_xdr.go message.go
|
//go:generate genxdr -o message_xdr.go message.go
|
||||||
|
|
||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sha256OfEmptyBlock = sha256.Sum256(make([]byte, BlockSize))
|
||||||
|
|
||||||
type IndexMessage struct {
|
type IndexMessage struct {
|
||||||
Folder string
|
Folder string // max:256
|
||||||
Files []FileInfo // max:1000000
|
Files []FileInfo // max:1000000
|
||||||
Flags uint32
|
Flags uint32
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
@ -33,9 +39,13 @@ func (f FileInfo) Size() (bytes int64) {
|
|||||||
if f.IsDeleted() || f.IsDirectory() {
|
if f.IsDeleted() || f.IsDirectory() {
|
||||||
return 128
|
return 128
|
||||||
}
|
}
|
||||||
|
if f.CachedSize > 0 {
|
||||||
|
return f.CachedSize
|
||||||
|
}
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
bytes += int64(b.Size)
|
bytes += int64(b.Size)
|
||||||
}
|
}
|
||||||
|
f.CachedSize = bytes
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +104,13 @@ func (b BlockInfo) String() string {
|
|||||||
return fmt.Sprintf("Block{%d/%d/%x}", b.Offset, b.Size, b.Hash)
|
return fmt.Sprintf("Block{%d/%d/%x}", b.Offset, b.Size, b.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if the block is a full block of zeroes.
|
||||||
|
func (b BlockInfo) IsEmpty() bool {
|
||||||
|
return b.Size == BlockSize && bytes.Equal(b.Hash, sha256OfEmptyBlock[:])
|
||||||
|
}
|
||||||
|
|
||||||
type RequestMessage struct {
|
type RequestMessage struct {
|
||||||
Folder string // max:64
|
Folder string // max:256
|
||||||
Name string // max:8192
|
Name string // max:8192
|
||||||
Offset int64
|
Offset int64
|
||||||
Size int32
|
Size int32
|
||||||
@ -110,6 +125,7 @@ type ResponseMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ClusterConfigMessage struct {
|
type ClusterConfigMessage struct {
|
||||||
|
DeviceName string // max:64
|
||||||
ClientName string // max:64
|
ClientName string // max:64
|
||||||
ClientVersion string // max:64
|
ClientVersion string // max:64
|
||||||
Folders []Folder // max:1000000
|
Folders []Folder // max:1000000
|
||||||
@ -126,14 +142,18 @@ func (o *ClusterConfigMessage) GetOption(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
ID string // max:64
|
ID string // max:256
|
||||||
Devices []Device // max:1000000
|
Devices []Device // max:1000000
|
||||||
Flags uint32
|
Flags uint32
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
}
|
}
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
ID []byte // max:32
|
ID []byte // max:32
|
||||||
|
Name string // max:64
|
||||||
|
Addresses []string // max:64,2083
|
||||||
|
Compression uint32
|
||||||
|
CertName string // max:64
|
||||||
MaxLocalVersion int64
|
MaxLocalVersion int64
|
||||||
Flags uint32
|
Flags uint32
|
||||||
Options []Option // max:64
|
Options []Option // max:64
|
||||||
|
@ -41,7 +41,7 @@ IndexMessage Structure:
|
|||||||
|
|
||||||
|
|
||||||
struct IndexMessage {
|
struct IndexMessage {
|
||||||
string Folder<>;
|
string Folder<256>;
|
||||||
FileInfo Files<1000000>;
|
FileInfo Files<1000000>;
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
@ -74,6 +74,9 @@ func (o IndexMessage) AppendXDR(bs []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o IndexMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
func (o IndexMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
if l := len(o.Folder); l > 256 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Folder", l, 256)
|
||||||
|
}
|
||||||
xw.WriteString(o.Folder)
|
xw.WriteString(o.Folder)
|
||||||
if l := len(o.Files); l > 1000000 {
|
if l := len(o.Files); l > 1000000 {
|
||||||
return xw.Tot(), xdr.ElementSizeExceeded("Files", l, 1000000)
|
return xw.Tot(), xdr.ElementSizeExceeded("Files", l, 1000000)
|
||||||
@ -111,7 +114,7 @@ func (o *IndexMessage) UnmarshalXDR(bs []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *IndexMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
func (o *IndexMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
o.Folder = xr.ReadString()
|
o.Folder = xr.ReadStringMax(256)
|
||||||
_FilesSize := int(xr.ReadUint32())
|
_FilesSize := int(xr.ReadUint32())
|
||||||
if _FilesSize < 0 {
|
if _FilesSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Files", _FilesSize, 1000000)
|
return xdr.ElementSizeExceeded("Files", _FilesSize, 1000000)
|
||||||
@ -380,7 +383,7 @@ RequestMessage Structure:
|
|||||||
|
|
||||||
|
|
||||||
struct RequestMessage {
|
struct RequestMessage {
|
||||||
string Folder<64>;
|
string Folder<256>;
|
||||||
string Name<8192>;
|
string Name<8192>;
|
||||||
hyper Offset;
|
hyper Offset;
|
||||||
int Size;
|
int Size;
|
||||||
@ -416,8 +419,8 @@ func (o RequestMessage) AppendXDR(bs []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o RequestMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
func (o RequestMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
if l := len(o.Folder); l > 64 {
|
if l := len(o.Folder); l > 256 {
|
||||||
return xw.Tot(), xdr.ElementSizeExceeded("Folder", l, 64)
|
return xw.Tot(), xdr.ElementSizeExceeded("Folder", l, 256)
|
||||||
}
|
}
|
||||||
xw.WriteString(o.Folder)
|
xw.WriteString(o.Folder)
|
||||||
if l := len(o.Name); l > 8192 {
|
if l := len(o.Name); l > 8192 {
|
||||||
@ -456,7 +459,7 @@ func (o *RequestMessage) UnmarshalXDR(bs []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *RequestMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
func (o *RequestMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
o.Folder = xr.ReadStringMax(64)
|
o.Folder = xr.ReadStringMax(256)
|
||||||
o.Name = xr.ReadStringMax(8192)
|
o.Name = xr.ReadStringMax(8192)
|
||||||
o.Offset = int64(xr.ReadUint64())
|
o.Offset = int64(xr.ReadUint64())
|
||||||
o.Size = int32(xr.ReadUint32())
|
o.Size = int32(xr.ReadUint32())
|
||||||
@ -554,6 +557,12 @@ ClusterConfigMessage Structure:
|
|||||||
0 1 2 3
|
0 1 2 3
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Device Name |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Device Name (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Length of Client Name |
|
| Length of Client Name |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
/ /
|
/ /
|
||||||
@ -581,6 +590,7 @@ ClusterConfigMessage Structure:
|
|||||||
|
|
||||||
|
|
||||||
struct ClusterConfigMessage {
|
struct ClusterConfigMessage {
|
||||||
|
string DeviceName<64>;
|
||||||
string ClientName<64>;
|
string ClientName<64>;
|
||||||
string ClientVersion<64>;
|
string ClientVersion<64>;
|
||||||
Folder Folders<1000000>;
|
Folder Folders<1000000>;
|
||||||
@ -614,6 +624,10 @@ func (o ClusterConfigMessage) AppendXDR(bs []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterConfigMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
func (o ClusterConfigMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
if l := len(o.DeviceName); l > 64 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("DeviceName", l, 64)
|
||||||
|
}
|
||||||
|
xw.WriteString(o.DeviceName)
|
||||||
if l := len(o.ClientName); l > 64 {
|
if l := len(o.ClientName); l > 64 {
|
||||||
return xw.Tot(), xdr.ElementSizeExceeded("ClientName", l, 64)
|
return xw.Tot(), xdr.ElementSizeExceeded("ClientName", l, 64)
|
||||||
}
|
}
|
||||||
@ -657,6 +671,7 @@ func (o *ClusterConfigMessage) UnmarshalXDR(bs []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *ClusterConfigMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
func (o *ClusterConfigMessage) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
o.DeviceName = xr.ReadStringMax(64)
|
||||||
o.ClientName = xr.ReadStringMax(64)
|
o.ClientName = xr.ReadStringMax(64)
|
||||||
o.ClientVersion = xr.ReadStringMax(64)
|
o.ClientVersion = xr.ReadStringMax(64)
|
||||||
_FoldersSize := int(xr.ReadUint32())
|
_FoldersSize := int(xr.ReadUint32())
|
||||||
@ -714,7 +729,7 @@ Folder Structure:
|
|||||||
|
|
||||||
|
|
||||||
struct Folder {
|
struct Folder {
|
||||||
string ID<64>;
|
string ID<256>;
|
||||||
Device Devices<1000000>;
|
Device Devices<1000000>;
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
@ -747,8 +762,8 @@ func (o Folder) AppendXDR(bs []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o Folder) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
func (o Folder) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
if l := len(o.ID); l > 64 {
|
if l := len(o.ID); l > 256 {
|
||||||
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 64)
|
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 256)
|
||||||
}
|
}
|
||||||
xw.WriteString(o.ID)
|
xw.WriteString(o.ID)
|
||||||
if l := len(o.Devices); l > 1000000 {
|
if l := len(o.Devices); l > 1000000 {
|
||||||
@ -787,7 +802,7 @@ func (o *Folder) UnmarshalXDR(bs []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Folder) DecodeXDRFrom(xr *xdr.Reader) error {
|
func (o *Folder) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
o.ID = xr.ReadStringMax(64)
|
o.ID = xr.ReadStringMax(256)
|
||||||
_DevicesSize := int(xr.ReadUint32())
|
_DevicesSize := int(xr.ReadUint32())
|
||||||
if _DevicesSize < 0 {
|
if _DevicesSize < 0 {
|
||||||
return xdr.ElementSizeExceeded("Devices", _DevicesSize, 1000000)
|
return xdr.ElementSizeExceeded("Devices", _DevicesSize, 1000000)
|
||||||
@ -827,6 +842,28 @@ Device Structure:
|
|||||||
\ ID (variable length) \
|
\ ID (variable length) \
|
||||||
/ /
|
/ /
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Name |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Name (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Number of Addresses |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Addresses |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Addresses (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Compression |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Length of Cert Name |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
/ /
|
||||||
|
\ Cert Name (variable length) \
|
||||||
|
/ /
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| |
|
| |
|
||||||
+ Max Local Version (64 bits) +
|
+ Max Local Version (64 bits) +
|
||||||
| |
|
| |
|
||||||
@ -843,6 +880,10 @@ Device Structure:
|
|||||||
|
|
||||||
struct Device {
|
struct Device {
|
||||||
opaque ID<32>;
|
opaque ID<32>;
|
||||||
|
string Name<64>;
|
||||||
|
string Addresses<64>;
|
||||||
|
unsigned int Compression;
|
||||||
|
string CertName<64>;
|
||||||
hyper MaxLocalVersion;
|
hyper MaxLocalVersion;
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
Option Options<64>;
|
Option Options<64>;
|
||||||
@ -879,6 +920,22 @@ func (o Device) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
|||||||
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 32)
|
return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 32)
|
||||||
}
|
}
|
||||||
xw.WriteBytes(o.ID)
|
xw.WriteBytes(o.ID)
|
||||||
|
if l := len(o.Name); l > 64 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Name", l, 64)
|
||||||
|
}
|
||||||
|
xw.WriteString(o.Name)
|
||||||
|
if l := len(o.Addresses); l > 64 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("Addresses", l, 64)
|
||||||
|
}
|
||||||
|
xw.WriteUint32(uint32(len(o.Addresses)))
|
||||||
|
for i := range o.Addresses {
|
||||||
|
xw.WriteString(o.Addresses[i])
|
||||||
|
}
|
||||||
|
xw.WriteUint32(o.Compression)
|
||||||
|
if l := len(o.CertName); l > 64 {
|
||||||
|
return xw.Tot(), xdr.ElementSizeExceeded("CertName", l, 64)
|
||||||
|
}
|
||||||
|
xw.WriteString(o.CertName)
|
||||||
xw.WriteUint64(uint64(o.MaxLocalVersion))
|
xw.WriteUint64(uint64(o.MaxLocalVersion))
|
||||||
xw.WriteUint32(o.Flags)
|
xw.WriteUint32(o.Flags)
|
||||||
if l := len(o.Options); l > 64 {
|
if l := len(o.Options); l > 64 {
|
||||||
@ -907,6 +964,20 @@ func (o *Device) UnmarshalXDR(bs []byte) error {
|
|||||||
|
|
||||||
func (o *Device) DecodeXDRFrom(xr *xdr.Reader) error {
|
func (o *Device) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
o.ID = xr.ReadBytesMax(32)
|
o.ID = xr.ReadBytesMax(32)
|
||||||
|
o.Name = xr.ReadStringMax(64)
|
||||||
|
_AddressesSize := int(xr.ReadUint32())
|
||||||
|
if _AddressesSize < 0 {
|
||||||
|
return xdr.ElementSizeExceeded("Addresses", _AddressesSize, 64)
|
||||||
|
}
|
||||||
|
if _AddressesSize > 64 {
|
||||||
|
return xdr.ElementSizeExceeded("Addresses", _AddressesSize, 64)
|
||||||
|
}
|
||||||
|
o.Addresses = make([]string, _AddressesSize)
|
||||||
|
for i := range o.Addresses {
|
||||||
|
o.Addresses[i] = xr.ReadStringMax(2083)
|
||||||
|
}
|
||||||
|
o.Compression = xr.ReadUint32()
|
||||||
|
o.CertName = xr.ReadStringMax(64)
|
||||||
o.MaxLocalVersion = int64(xr.ReadUint64())
|
o.MaxLocalVersion = int64(xr.ReadUint64())
|
||||||
o.Flags = xr.ReadUint32()
|
o.Flags = xr.ReadUint32()
|
||||||
_OptionsSize := int(xr.ReadUint32())
|
_OptionsSize := int(xr.ReadUint32())
|
||||||
|
@ -15,10 +15,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Data block size (128 KiB)
|
// BlockSize is the standard ata block size (128 KiB)
|
||||||
BlockSize = 128 << 10
|
BlockSize = 128 << 10
|
||||||
|
|
||||||
// We reject messages larger than this when encountered on the wire. (64 MiB)
|
// MaxMessageLen is the largest message size allowed on the wire. (64 MiB)
|
||||||
MaxMessageLen = 64 << 20
|
MaxMessageLen = 64 << 20
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -61,6 +61,13 @@ const (
|
|||||||
FlagRequestTemporary uint32 = 1 << iota
|
FlagRequestTemporary uint32 = 1 << iota
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ClusterConfigMessage.Folders flags
|
||||||
|
const (
|
||||||
|
FlagFolderReadOnly uint32 = 1 << 0
|
||||||
|
FlagFolderIgnorePerms = 1 << 1
|
||||||
|
FlagFolderIgnoreDelete = 1 << 2
|
||||||
|
)
|
||||||
|
|
||||||
// ClusterConfigMessage.Folders.Devices flags
|
// ClusterConfigMessage.Folders.Devices flags
|
||||||
const (
|
const (
|
||||||
FlagShareTrusted uint32 = 1 << 0
|
FlagShareTrusted uint32 = 1 << 0
|
||||||
@ -145,9 +152,11 @@ type isEofer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// We make sure to send a message at least this often, by triggering pings.
|
// PingSendInterval is how often we make sure to send a message, by
|
||||||
|
// triggering pings if necessary.
|
||||||
PingSendInterval = 90 * time.Second
|
PingSendInterval = 90 * time.Second
|
||||||
// If we haven't received a message from the other side for this long, close the connection.
|
// ReceiveTimeout is the longest we'll wait for a message from the other
|
||||||
|
// side before closing the connection.
|
||||||
ReceiveTimeout = 300 * time.Second
|
ReceiveTimeout = 300 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -367,9 +376,7 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
hdr = decodeHeader(binary.BigEndian.Uint32(c.rdbuf0[0:4]))
|
hdr = decodeHeader(binary.BigEndian.Uint32(c.rdbuf0[0:4]))
|
||||||
msglen := int(binary.BigEndian.Uint32(c.rdbuf0[4:8]))
|
msglen := int(binary.BigEndian.Uint32(c.rdbuf0[4:8]))
|
||||||
|
|
||||||
if debug {
|
l.Debugf("read header %v (msglen=%d)", hdr, msglen)
|
||||||
l.Debugf("read header %v (msglen=%d)", hdr, msglen)
|
|
||||||
}
|
|
||||||
|
|
||||||
if msglen > MaxMessageLen {
|
if msglen > MaxMessageLen {
|
||||||
err = fmt.Errorf("message length %d exceeds maximum %d", msglen, MaxMessageLen)
|
err = fmt.Errorf("message length %d exceeds maximum %d", msglen, MaxMessageLen)
|
||||||
@ -391,9 +398,7 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
l.Debugf("read %d bytes", len(c.rdbuf0))
|
||||||
l.Debugf("read %d bytes", len(c.rdbuf0))
|
|
||||||
}
|
|
||||||
|
|
||||||
msgBuf := c.rdbuf0
|
msgBuf := c.rdbuf0
|
||||||
if hdr.compression && msglen > 0 {
|
if hdr.compression && msglen > 0 {
|
||||||
@ -403,12 +408,10 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
msgBuf = c.rdbuf1
|
msgBuf = c.rdbuf1
|
||||||
if debug {
|
l.Debugf("decompressed to %d bytes", len(msgBuf))
|
||||||
l.Debugf("decompressed to %d bytes", len(msgBuf))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if shouldDebug() {
|
||||||
if len(msgBuf) > 1024 {
|
if len(msgBuf) > 1024 {
|
||||||
l.Debugf("message data:\n%s", hex.Dump(msgBuf[:1024]))
|
l.Debugf("message data:\n%s", hex.Dump(msgBuf[:1024]))
|
||||||
} else {
|
} else {
|
||||||
@ -475,16 +478,12 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *rawConnection) handleIndex(im IndexMessage) {
|
func (c *rawConnection) handleIndex(im IndexMessage) {
|
||||||
if debug {
|
l.Debugf("Index(%v, %v, %d file, flags %x, opts: %s)", c.id, im.Folder, len(im.Files), im.Flags, im.Options)
|
||||||
l.Debugf("Index(%v, %v, %d file, flags %x, opts: %s)", c.id, im.Folder, len(im.Files), im.Flags, im.Options)
|
|
||||||
}
|
|
||||||
c.receiver.Index(c.id, im.Folder, filterIndexMessageFiles(im.Files), im.Flags, im.Options)
|
c.receiver.Index(c.id, im.Folder, filterIndexMessageFiles(im.Files), im.Flags, im.Options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rawConnection) handleIndexUpdate(im IndexMessage) {
|
func (c *rawConnection) handleIndexUpdate(im IndexMessage) {
|
||||||
if debug {
|
l.Debugf("queueing IndexUpdate(%v, %v, %d files, flags %x, opts: %s)", c.id, im.Folder, len(im.Files), im.Flags, im.Options)
|
||||||
l.Debugf("queueing IndexUpdate(%v, %v, %d files, flags %x, opts: %s)", c.id, im.Folder, len(im.Files), im.Flags, im.Options)
|
|
||||||
}
|
|
||||||
c.receiver.IndexUpdate(c.id, im.Folder, filterIndexMessageFiles(im.Files), im.Flags, im.Options)
|
c.receiver.IndexUpdate(c.id, im.Folder, filterIndexMessageFiles(im.Files), im.Flags, im.Options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,9 +633,7 @@ func (c *rawConnection) writerLoop() {
|
|||||||
binary.BigEndian.PutUint32(msgBuf[4:8], uint32(len(tempBuf)))
|
binary.BigEndian.PutUint32(msgBuf[4:8], uint32(len(tempBuf)))
|
||||||
msgBuf = msgBuf[0 : len(tempBuf)+8]
|
msgBuf = msgBuf[0 : len(tempBuf)+8]
|
||||||
|
|
||||||
if debug {
|
l.Debugf("write compressed message; %v (len=%d)", hm.hdr, len(tempBuf))
|
||||||
l.Debugf("write compressed message; %v (len=%d)", hm.hdr, len(tempBuf))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// No point in compressing very short messages
|
// No point in compressing very short messages
|
||||||
hm.hdr.compression = false
|
hm.hdr.compression = false
|
||||||
@ -650,14 +647,10 @@ func (c *rawConnection) writerLoop() {
|
|||||||
msgBuf = msgBuf[0 : len(uncBuf)+8]
|
msgBuf = msgBuf[0 : len(uncBuf)+8]
|
||||||
copy(msgBuf[8:], uncBuf)
|
copy(msgBuf[8:], uncBuf)
|
||||||
|
|
||||||
if debug {
|
l.Debugf("write uncompressed message; %v (len=%d)", hm.hdr, len(uncBuf))
|
||||||
l.Debugf("write uncompressed message; %v (len=%d)", hm.hdr, len(uncBuf))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if debug {
|
l.Debugf("write empty message; %v", hm.hdr)
|
||||||
l.Debugf("write empty message; %v", hm.hdr)
|
|
||||||
}
|
|
||||||
binary.BigEndian.PutUint32(msgBuf[4:8], 0)
|
binary.BigEndian.PutUint32(msgBuf[4:8], 0)
|
||||||
msgBuf = msgBuf[:8]
|
msgBuf = msgBuf[:8]
|
||||||
}
|
}
|
||||||
@ -667,9 +660,7 @@ func (c *rawConnection) writerLoop() {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
var n int
|
var n int
|
||||||
n, err = c.cw.Write(msgBuf)
|
n, err = c.cw.Write(msgBuf)
|
||||||
if debug {
|
l.Debugf("wrote %d bytes on the wire", n)
|
||||||
l.Debugf("wrote %d bytes on the wire", n)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.close(err)
|
c.close(err)
|
||||||
@ -723,15 +714,11 @@ func (c *rawConnection) pingSender() {
|
|||||||
case <-ticker:
|
case <-ticker:
|
||||||
d := time.Since(c.cw.Last())
|
d := time.Since(c.cw.Last())
|
||||||
if d < PingSendInterval/2 {
|
if d < PingSendInterval/2 {
|
||||||
if debug {
|
l.Debugln(c.id, "ping skipped after wr", d)
|
||||||
l.Debugln(c.id, "ping skipped after wr", d)
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
l.Debugln(c.id, "ping -> after", d)
|
||||||
l.Debugln(c.id, "ping -> after", d)
|
|
||||||
}
|
|
||||||
c.ping()
|
c.ping()
|
||||||
|
|
||||||
case <-c.closed:
|
case <-c.closed:
|
||||||
@ -751,15 +738,11 @@ func (c *rawConnection) pingReceiver() {
|
|||||||
case <-ticker:
|
case <-ticker:
|
||||||
d := time.Since(c.cr.Last())
|
d := time.Since(c.cr.Last())
|
||||||
if d > ReceiveTimeout {
|
if d > ReceiveTimeout {
|
||||||
if debug {
|
l.Debugln(c.id, "ping timeout", d)
|
||||||
l.Debugln(c.id, "ping timeout", d)
|
|
||||||
}
|
|
||||||
c.close(ErrTimeout)
|
c.close(ErrTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
l.Debugln(c.id, "last read within", d)
|
||||||
l.Debugln(c.id, "last read within", d)
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-c.closed:
|
case <-c.closed:
|
||||||
return
|
return
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -19,11 +20,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
c0ID = NewDeviceID([]byte{1})
|
c0ID = NewDeviceID([]byte{1})
|
||||||
c1ID = NewDeviceID([]byte{2})
|
c1ID = NewDeviceID([]byte{2})
|
||||||
|
quickCfg = &quick.Config{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
flag.Parse()
|
||||||
|
if flag.Lookup("test.short").Value.String() != "false" {
|
||||||
|
quickCfg.MaxCount = 10
|
||||||
|
}
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
||||||
|
|
||||||
func TestHeaderFunctions(t *testing.T) {
|
func TestHeaderFunctions(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
f := func(ver, id, typ int) bool {
|
f := func(ver, id, typ int) bool {
|
||||||
ver = int(uint(ver) % 16)
|
ver = int(uint(ver) % 16)
|
||||||
id = int(uint(id) % 4096)
|
id = int(uint(id) % 4096)
|
||||||
@ -38,6 +49,7 @@ func TestHeaderFunctions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHeaderLayout(t *testing.T) {
|
func TestHeaderLayout(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
var e, a uint32
|
var e, a uint32
|
||||||
|
|
||||||
// Version are the first four bits
|
// Version are the first four bits
|
||||||
@ -63,6 +75,7 @@ func TestHeaderLayout(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPing(t *testing.T) {
|
func TestPing(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
ar, aw := io.Pipe()
|
ar, aw := io.Pipe()
|
||||||
br, bw := io.Pipe()
|
br, bw := io.Pipe()
|
||||||
|
|
||||||
@ -82,6 +95,7 @@ func TestPing(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVersionErr(t *testing.T) {
|
func TestVersionErr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
m0 := newTestModel()
|
m0 := newTestModel()
|
||||||
m1 := newTestModel()
|
m1 := newTestModel()
|
||||||
|
|
||||||
@ -109,6 +123,7 @@ func TestVersionErr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTypeErr(t *testing.T) {
|
func TestTypeErr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
m0 := newTestModel()
|
m0 := newTestModel()
|
||||||
m1 := newTestModel()
|
m1 := newTestModel()
|
||||||
|
|
||||||
@ -136,6 +151,7 @@ func TestTypeErr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClose(t *testing.T) {
|
func TestClose(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
m0 := newTestModel()
|
m0 := newTestModel()
|
||||||
m1 := newTestModel()
|
m1 := newTestModel()
|
||||||
|
|
||||||
@ -171,10 +187,9 @@ func TestClose(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestElementSizeExceededNested(t *testing.T) {
|
func TestElementSizeExceededNested(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
m := ClusterConfigMessage{
|
m := ClusterConfigMessage{
|
||||||
Folders: []Folder{
|
ClientName: "longstringlongstringlongstringinglongstringlongstringlonlongstringlongstringlon",
|
||||||
{ID: "longstringlongstringlongstringinglongstringlongstringlonlongstringlongstringlon"},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
_, err := m.EncodeXDR(ioutil.Discard)
|
_, err := m.EncodeXDR(ioutil.Discard)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -183,11 +198,7 @@ func TestElementSizeExceededNested(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalIndexMessage(t *testing.T) {
|
func TestMarshalIndexMessage(t *testing.T) {
|
||||||
var quickCfg = &quick.Config{MaxCountScale: 10}
|
t.Parallel()
|
||||||
if testing.Short() {
|
|
||||||
quickCfg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(m1 IndexMessage) bool {
|
f := func(m1 IndexMessage) bool {
|
||||||
for i, f := range m1.Files {
|
for i, f := range m1.Files {
|
||||||
m1.Files[i].CachedSize = 0
|
m1.Files[i].CachedSize = 0
|
||||||
@ -208,11 +219,7 @@ func TestMarshalIndexMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalRequestMessage(t *testing.T) {
|
func TestMarshalRequestMessage(t *testing.T) {
|
||||||
var quickCfg = &quick.Config{MaxCountScale: 10}
|
t.Parallel()
|
||||||
if testing.Short() {
|
|
||||||
quickCfg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(m1 RequestMessage) bool {
|
f := func(m1 RequestMessage) bool {
|
||||||
return testMarshal(t, "request", &m1, &RequestMessage{})
|
return testMarshal(t, "request", &m1, &RequestMessage{})
|
||||||
}
|
}
|
||||||
@ -223,11 +230,7 @@ func TestMarshalRequestMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalResponseMessage(t *testing.T) {
|
func TestMarshalResponseMessage(t *testing.T) {
|
||||||
var quickCfg = &quick.Config{MaxCountScale: 10}
|
t.Parallel()
|
||||||
if testing.Short() {
|
|
||||||
quickCfg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(m1 ResponseMessage) bool {
|
f := func(m1 ResponseMessage) bool {
|
||||||
if len(m1.Data) == 0 {
|
if len(m1.Data) == 0 {
|
||||||
m1.Data = nil
|
m1.Data = nil
|
||||||
@ -241,11 +244,7 @@ func TestMarshalResponseMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalClusterConfigMessage(t *testing.T) {
|
func TestMarshalClusterConfigMessage(t *testing.T) {
|
||||||
var quickCfg = &quick.Config{MaxCountScale: 10}
|
t.Parallel()
|
||||||
if testing.Short() {
|
|
||||||
quickCfg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(m1 ClusterConfigMessage) bool {
|
f := func(m1 ClusterConfigMessage) bool {
|
||||||
return testMarshal(t, "clusterconfig", &m1, &ClusterConfigMessage{})
|
return testMarshal(t, "clusterconfig", &m1, &ClusterConfigMessage{})
|
||||||
}
|
}
|
||||||
@ -256,11 +255,7 @@ func TestMarshalClusterConfigMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalCloseMessage(t *testing.T) {
|
func TestMarshalCloseMessage(t *testing.T) {
|
||||||
var quickCfg = &quick.Config{MaxCountScale: 10}
|
t.Parallel()
|
||||||
if testing.Short() {
|
|
||||||
quickCfg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(m1 CloseMessage) bool {
|
f := func(m1 CloseMessage) bool {
|
||||||
return testMarshal(t, "close", &m1, &CloseMessage{})
|
return testMarshal(t, "close", &m1, &CloseMessage{})
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ package protocol
|
|||||||
|
|
||||||
// The Vector type represents a version vector. The zero value is a usable
|
// The Vector type represents a version vector. The zero value is a usable
|
||||||
// version vector. The vector has slice semantics and some operations on it
|
// version vector. The vector has slice semantics and some operations on it
|
||||||
// are "append-like" in that they may return the same vector modified, or a
|
// are "append-like" in that they may return the same vector modified, or v
|
||||||
// new allocated Vector with the modified contents.
|
// new allocated Vector with the modified contents.
|
||||||
type Vector []Counter
|
type Vector []Counter
|
||||||
|
|
||||||
@ -33,43 +33,43 @@ func (v Vector) Update(ID uint64) Vector {
|
|||||||
return nv
|
return nv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Append a new new index
|
// Append a new index
|
||||||
return append(v, Counter{ID, 1})
|
return append(v, Counter{ID, 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge returns the vector containing the maximum indexes from a and b. If it
|
// Merge returns the vector containing the maximum indexes from v and b. If it
|
||||||
// is possible, the vector a is updated and returned. If it is not, a copy
|
// is possible, the vector v is updated and returned. If it is not, a copy
|
||||||
// will be created, updated and returned.
|
// will be created, updated and returned.
|
||||||
func (a Vector) Merge(b Vector) Vector {
|
func (v Vector) Merge(b Vector) Vector {
|
||||||
var ai, bi int
|
var vi, bi int
|
||||||
for bi < len(b) {
|
for bi < len(b) {
|
||||||
if ai == len(a) {
|
if vi == len(v) {
|
||||||
// We've reach the end of a, all that remains are appends
|
// We've reach the end of v, all that remains are appends
|
||||||
return append(a, b[bi:]...)
|
return append(v, b[bi:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a[ai].ID > b[bi].ID {
|
if v[vi].ID > b[bi].ID {
|
||||||
// The index from b should be inserted here
|
// The index from b should be inserted here
|
||||||
n := make(Vector, len(a)+1)
|
n := make(Vector, len(v)+1)
|
||||||
copy(n, a[:ai])
|
copy(n, v[:vi])
|
||||||
n[ai] = b[bi]
|
n[vi] = b[bi]
|
||||||
copy(n[ai+1:], a[ai:])
|
copy(n[vi+1:], v[vi:])
|
||||||
a = n
|
v = n
|
||||||
}
|
}
|
||||||
|
|
||||||
if a[ai].ID == b[bi].ID {
|
if v[vi].ID == b[bi].ID {
|
||||||
if v := b[bi].Value; v > a[ai].Value {
|
if val := b[bi].Value; val > v[vi].Value {
|
||||||
a[ai].Value = v
|
v[vi].Value = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if bi < len(b) && a[ai].ID == b[bi].ID {
|
if bi < len(b) && v[vi].ID == b[bi].ID {
|
||||||
bi++
|
bi++
|
||||||
}
|
}
|
||||||
ai++
|
vi++
|
||||||
}
|
}
|
||||||
|
|
||||||
return a
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns an identical vector that is not shared with v.
|
// Copy returns an identical vector that is not shared with v.
|
||||||
@ -80,27 +80,27 @@ func (v Vector) Copy() Vector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Equal returns true when the two vectors are equivalent.
|
// Equal returns true when the two vectors are equivalent.
|
||||||
func (a Vector) Equal(b Vector) bool {
|
func (v Vector) Equal(b Vector) bool {
|
||||||
return a.Compare(b) == Equal
|
return v.Compare(b) == Equal
|
||||||
}
|
}
|
||||||
|
|
||||||
// LesserEqual returns true when the two vectors are equivalent or a is Lesser
|
// LesserEqual returns true when the two vectors are equivalent or v is Lesser
|
||||||
// than b.
|
// than b.
|
||||||
func (a Vector) LesserEqual(b Vector) bool {
|
func (v Vector) LesserEqual(b Vector) bool {
|
||||||
comp := a.Compare(b)
|
comp := v.Compare(b)
|
||||||
return comp == Lesser || comp == Equal
|
return comp == Lesser || comp == Equal
|
||||||
}
|
}
|
||||||
|
|
||||||
// LesserEqual returns true when the two vectors are equivalent or a is Greater
|
// GreaterEqual returns true when the two vectors are equivalent or v is Greater
|
||||||
// than b.
|
// than b.
|
||||||
func (a Vector) GreaterEqual(b Vector) bool {
|
func (v Vector) GreaterEqual(b Vector) bool {
|
||||||
comp := a.Compare(b)
|
comp := v.Compare(b)
|
||||||
return comp == Greater || comp == Equal
|
return comp == Greater || comp == Equal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concurrent returns true when the two vectors are concrurrent.
|
// Concurrent returns true when the two vectors are concrurrent.
|
||||||
func (a Vector) Concurrent(b Vector) bool {
|
func (v Vector) Concurrent(b Vector) bool {
|
||||||
comp := a.Compare(b)
|
comp := v.Compare(b)
|
||||||
return comp == ConcurrentGreater || comp == ConcurrentLesser
|
return comp == ConcurrentGreater || comp == ConcurrentLesser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,12 @@ func TestMerge(t *testing.T) {
|
|||||||
func TestCounterValue(t *testing.T) {
|
func TestCounterValue(t *testing.T) {
|
||||||
v0 := Vector{Counter{42, 1}, Counter{64, 5}}
|
v0 := Vector{Counter{42, 1}, Counter{64, 5}}
|
||||||
if v0.Counter(42) != 1 {
|
if v0.Counter(42) != 1 {
|
||||||
t.Error("Counter error, %d != %d", v0.Counter(42), 1)
|
t.Errorf("Counter error, %d != %d", v0.Counter(42), 1)
|
||||||
}
|
}
|
||||||
if v0.Counter(64) != 5 {
|
if v0.Counter(64) != 5 {
|
||||||
t.Error("Counter error, %d != %d", v0.Counter(64), 5)
|
t.Errorf("Counter error, %d != %d", v0.Counter(64), 5)
|
||||||
}
|
}
|
||||||
if v0.Counter(72) != 0 {
|
if v0.Counter(72) != 0 {
|
||||||
t.Error("Counter error, %d != %d", v0.Counter(72), 0)
|
t.Errorf("Counter error, %d != %d", v0.Counter(72), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,294 +5,37 @@ package client
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
|
||||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||||
"github.com/syncthing/syncthing/lib/sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProtocolClient struct {
|
type relayClientFactory func(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) RelayClient
|
||||||
URI *url.URL
|
|
||||||
Invitations chan protocol.SessionInvitation
|
|
||||||
|
|
||||||
closeInvitationsOnFinish bool
|
var (
|
||||||
|
supportedSchemes = map[string]relayClientFactory{
|
||||||
|
"relay": newStaticClient,
|
||||||
|
"dynamic+http": newDynamicClient,
|
||||||
|
"dynamic+https": newDynamicClient,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
config *tls.Config
|
type RelayClient interface {
|
||||||
|
Serve()
|
||||||
timeout time.Duration
|
Stop()
|
||||||
|
StatusOK() bool
|
||||||
stop chan struct{}
|
Latency() time.Duration
|
||||||
stopped chan struct{}
|
String() string
|
||||||
|
Invitations() chan protocol.SessionInvitation
|
||||||
conn *tls.Conn
|
URI() *url.URL
|
||||||
|
|
||||||
mut sync.RWMutex
|
|
||||||
connected bool
|
|
||||||
latency time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProtocolClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) *ProtocolClient {
|
func NewClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) (RelayClient, error) {
|
||||||
closeInvitationsOnFinish := false
|
factory, ok := supportedSchemes[uri.Scheme]
|
||||||
if invitations == nil {
|
if !ok {
|
||||||
closeInvitationsOnFinish = true
|
return nil, fmt.Errorf("Unsupported scheme: %s", uri.Scheme)
|
||||||
invitations = make(chan protocol.SessionInvitation)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ProtocolClient{
|
return factory(uri, certs, invitations, timeout), nil
|
||||||
URI: uri,
|
|
||||||
Invitations: invitations,
|
|
||||||
|
|
||||||
closeInvitationsOnFinish: closeInvitationsOnFinish,
|
|
||||||
|
|
||||||
config: configForCerts(certs),
|
|
||||||
|
|
||||||
timeout: time.Minute * 2,
|
|
||||||
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
stopped: make(chan struct{}),
|
|
||||||
|
|
||||||
mut: sync.NewRWMutex(),
|
|
||||||
connected: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) Serve() {
|
|
||||||
c.stop = make(chan struct{})
|
|
||||||
c.stopped = make(chan struct{})
|
|
||||||
defer close(c.stopped)
|
|
||||||
|
|
||||||
if err := c.connect(); err != nil {
|
|
||||||
if debug {
|
|
||||||
l.Debugln("Relay connect:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "connected", c.conn.RemoteAddr())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.join(); err != nil {
|
|
||||||
c.conn.Close()
|
|
||||||
l.Infoln("Relay join:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.conn.SetDeadline(time.Time{}); err != nil {
|
|
||||||
l.Infoln("Relay set deadline:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "joined", c.conn.RemoteAddr(), "via", c.conn.LocalAddr())
|
|
||||||
}
|
|
||||||
|
|
||||||
defer c.cleanup()
|
|
||||||
c.mut.Lock()
|
|
||||||
c.connected = true
|
|
||||||
c.mut.Unlock()
|
|
||||||
|
|
||||||
messages := make(chan interface{})
|
|
||||||
errors := make(chan error, 1)
|
|
||||||
|
|
||||||
go messageReader(c.conn, messages, errors)
|
|
||||||
|
|
||||||
timeout := time.NewTimer(c.timeout)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case message := <-messages:
|
|
||||||
timeout.Reset(c.timeout)
|
|
||||||
if debug {
|
|
||||||
log.Printf("%s received message %T", c, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch msg := message.(type) {
|
|
||||||
case protocol.Ping:
|
|
||||||
if err := protocol.WriteMessage(c.conn, protocol.Pong{}); err != nil {
|
|
||||||
l.Infoln("Relay write:", err)
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "sent pong")
|
|
||||||
}
|
|
||||||
|
|
||||||
case protocol.SessionInvitation:
|
|
||||||
ip := net.IP(msg.Address)
|
|
||||||
if len(ip) == 0 || ip.IsUnspecified() {
|
|
||||||
msg.Address = c.conn.RemoteAddr().(*net.TCPAddr).IP[:]
|
|
||||||
}
|
|
||||||
c.Invitations <- msg
|
|
||||||
|
|
||||||
default:
|
|
||||||
l.Infoln("Relay: protocol error: unexpected message %v", msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-c.stop:
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "stopping")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
case err := <-errors:
|
|
||||||
l.Infoln("Relay received:", err)
|
|
||||||
return
|
|
||||||
|
|
||||||
case <-timeout.C:
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "timed out")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) Stop() {
|
|
||||||
if c.stop == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
close(c.stop)
|
|
||||||
<-c.stopped
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) StatusOK() bool {
|
|
||||||
c.mut.RLock()
|
|
||||||
con := c.connected
|
|
||||||
c.mut.RUnlock()
|
|
||||||
return con
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) Latency() time.Duration {
|
|
||||||
c.mut.RLock()
|
|
||||||
lat := c.latency
|
|
||||||
c.mut.RUnlock()
|
|
||||||
return lat
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) String() string {
|
|
||||||
return fmt.Sprintf("ProtocolClient@%p", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) connect() error {
|
|
||||||
if c.URI.Scheme != "relay" {
|
|
||||||
return fmt.Errorf("Unsupported relay schema:", c.URI.Scheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
t0 := time.Now()
|
|
||||||
tcpConn, err := net.Dial("tcp", c.URI.Host)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.mut.Lock()
|
|
||||||
c.latency = time.Since(t0)
|
|
||||||
c.mut.Unlock()
|
|
||||||
|
|
||||||
conn := tls.Client(tcpConn, c.config)
|
|
||||||
if err = conn.Handshake(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := performHandshakeAndValidation(conn, c.URI); err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.conn = conn
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) cleanup() {
|
|
||||||
if c.closeInvitationsOnFinish {
|
|
||||||
close(c.Invitations)
|
|
||||||
c.Invitations = make(chan protocol.SessionInvitation)
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
l.Debugln(c, "cleaning up")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.mut.Lock()
|
|
||||||
c.connected = false
|
|
||||||
c.mut.Unlock()
|
|
||||||
|
|
||||||
c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ProtocolClient) join() error {
|
|
||||||
if err := protocol.WriteMessage(c.conn, protocol.JoinRelayRequest{}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
message, err := protocol.ReadMessage(c.conn)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch msg := message.(type) {
|
|
||||||
case protocol.Response:
|
|
||||||
if msg.Code != 0 {
|
|
||||||
return fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("protocol error: expecting response got %v", msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
|
|
||||||
if err := conn.Handshake(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := conn.ConnectionState()
|
|
||||||
if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != protocol.ProtocolName {
|
|
||||||
return fmt.Errorf("protocol negotiation error")
|
|
||||||
}
|
|
||||||
|
|
||||||
q := uri.Query()
|
|
||||||
relayIDs := q.Get("id")
|
|
||||||
if relayIDs != "" {
|
|
||||||
relayID, err := syncthingprotocol.DeviceIDFromString(relayIDs)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("relay address contains invalid verification id: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certs := cs.PeerCertificates
|
|
||||||
if cl := len(certs); cl != 1 {
|
|
||||||
return fmt.Errorf("unexpected certificate count: %d", cl)
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteID := syncthingprotocol.NewDeviceID(certs[0].Raw)
|
|
||||||
if remoteID != relayID {
|
|
||||||
return fmt.Errorf("relay id does not match. Expected %v got %v", relayID, remoteID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func messageReader(conn net.Conn, messages chan<- interface{}, errors chan<- error) {
|
|
||||||
for {
|
|
||||||
msg, err := protocol.ReadMessage(conn)
|
|
||||||
if err != nil {
|
|
||||||
errors <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
messages <- msg
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/calmh/logger"
|
"github.com/syncthing/syncthing/lib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debug = strings.Contains(os.Getenv("STTRACE"), "relay") || os.Getenv("STTRACE") == "all"
|
l = logger.DefaultLogger.NewFacility("relay", "")
|
||||||
l = logger.DefaultLogger
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
l.SetDebug("relay", strings.Contains(os.Getenv("STTRACE"), "relay") || os.Getenv("STTRACE") == "all")
|
||||||
|
}
|
||||||
|
@ -11,20 +11,23 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/dialer"
|
||||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
||||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate) (protocol.SessionInvitation, error) {
|
func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate, timeout time.Duration) (protocol.SessionInvitation, error) {
|
||||||
if uri.Scheme != "relay" {
|
if uri.Scheme != "relay" {
|
||||||
return protocol.SessionInvitation{}, fmt.Errorf("Unsupported relay scheme:", uri.Scheme)
|
return protocol.SessionInvitation{}, fmt.Errorf("Unsupported relay scheme: %v", uri.Scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := tls.Dial("tcp", uri.Host, configForCerts(certs))
|
rconn, err := dialer.Dial("tcp", uri.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return protocol.SessionInvitation{}, err
|
return protocol.SessionInvitation{}, err
|
||||||
}
|
}
|
||||||
conn.SetDeadline(time.Now().Add(10 * time.Second))
|
|
||||||
|
conn := tls.Client(rconn, configForCerts(certs))
|
||||||
|
conn.SetDeadline(time.Now().Add(timeout))
|
||||||
|
|
||||||
if err := performHandshakeAndValidation(conn, uri); err != nil {
|
if err := performHandshakeAndValidation(conn, uri); err != nil {
|
||||||
return protocol.SessionInvitation{}, err
|
return protocol.SessionInvitation{}, err
|
||||||
@ -49,9 +52,7 @@ func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs [
|
|||||||
case protocol.Response:
|
case protocol.Response:
|
||||||
return protocol.SessionInvitation{}, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
return protocol.SessionInvitation{}, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
|
||||||
case protocol.SessionInvitation:
|
case protocol.SessionInvitation:
|
||||||
if debug {
|
l.Debugln("Received invitation", msg, "via", conn.LocalAddr())
|
||||||
l.Debugln("Received invitation", msg, "via", conn.LocalAddr())
|
|
||||||
}
|
|
||||||
ip := net.IP(msg.Address)
|
ip := net.IP(msg.Address)
|
||||||
if len(ip) == 0 || ip.IsUnspecified() {
|
if len(ip) == 0 || ip.IsUnspecified() {
|
||||||
msg.Address = conn.RemoteAddr().(*net.TCPAddr).IP[:]
|
msg.Address = conn.RemoteAddr().(*net.TCPAddr).IP[:]
|
||||||
@ -65,7 +66,7 @@ func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs [
|
|||||||
func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) {
|
func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) {
|
||||||
addr := net.JoinHostPort(net.IP(invitation.Address).String(), strconv.Itoa(int(invitation.Port)))
|
addr := net.JoinHostPort(net.IP(invitation.Address).String(), strconv.Itoa(int(invitation.Port)))
|
||||||
|
|
||||||
conn, err := net.Dial("tcp", addr)
|
conn, err := dialer.Dial("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -98,18 +99,22 @@ func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRelay(uri *url.URL, certs []tls.Certificate, sleep time.Duration, times int) bool {
|
func TestRelay(uri *url.URL, certs []tls.Certificate, sleep, timeout time.Duration, times int) bool {
|
||||||
id := syncthingprotocol.NewDeviceID(certs[0].Certificate[0])
|
id := syncthingprotocol.NewDeviceID(certs[0].Certificate[0])
|
||||||
invs := make(chan protocol.SessionInvitation, 1)
|
invs := make(chan protocol.SessionInvitation, 1)
|
||||||
c := NewProtocolClient(uri, certs, invs)
|
c, err := NewClient(uri, certs, invs, timeout)
|
||||||
|
if err != nil {
|
||||||
|
close(invs)
|
||||||
|
return false
|
||||||
|
}
|
||||||
go c.Serve()
|
go c.Serve()
|
||||||
defer func() {
|
defer func() {
|
||||||
close(invs)
|
|
||||||
c.Stop()
|
c.Stop()
|
||||||
|
close(invs)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for i := 0; i < times; i++ {
|
for i := 0; i < times; i++ {
|
||||||
_, err := GetInvitationFromRelay(uri, id, certs)
|
_, err := GetInvitationFromRelay(uri, id, certs, timeout)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||||
|
|
||||||
//go:generate -command genxdr go run ../../syncthing/Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
|
//go:generate -command genxdr go run ../../../Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
|
||||||
//go:generate genxdr -o packets_xdr.go packets.go
|
//go:generate genxdr -o packets_xdr.go packets.go
|
||||||
|
|
||||||
package protocol
|
package protocol
|
||||||
@ -20,6 +20,7 @@ const (
|
|||||||
messageTypeResponse
|
messageTypeResponse
|
||||||
messageTypeConnectRequest
|
messageTypeConnectRequest
|
||||||
messageTypeSessionInvitation
|
messageTypeSessionInvitation
|
||||||
|
messageTypeRelayFull
|
||||||
)
|
)
|
||||||
|
|
||||||
type header struct {
|
type header struct {
|
||||||
@ -31,6 +32,7 @@ type header struct {
|
|||||||
type Ping struct{}
|
type Ping struct{}
|
||||||
type Pong struct{}
|
type Pong struct{}
|
||||||
type JoinRelayRequest struct{}
|
type JoinRelayRequest struct{}
|
||||||
|
type RelayFull struct{}
|
||||||
|
|
||||||
type JoinSessionRequest struct {
|
type JoinSessionRequest struct {
|
||||||
Key []byte // max:32
|
Key []byte // max:32
|
||||||
|
@ -256,6 +256,63 @@ func (o *JoinRelayRequest) DecodeXDRFrom(xr *xdr.Reader) error {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
RelayFull Structure:
|
||||||
|
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
|
||||||
|
struct RelayFull {
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (o RelayFull) EncodeXDR(w io.Writer) (int, error) {
|
||||||
|
var xw = xdr.NewWriter(w)
|
||||||
|
return o.EncodeXDRInto(xw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o RelayFull) MarshalXDR() ([]byte, error) {
|
||||||
|
return o.AppendXDR(make([]byte, 0, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o RelayFull) MustMarshalXDR() []byte {
|
||||||
|
bs, err := o.MarshalXDR()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o RelayFull) AppendXDR(bs []byte) ([]byte, error) {
|
||||||
|
var aw = xdr.AppendWriter(bs)
|
||||||
|
var xw = xdr.NewWriter(&aw)
|
||||||
|
_, err := o.EncodeXDRInto(xw)
|
||||||
|
return []byte(aw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o RelayFull) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||||
|
return xw.Tot(), xw.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RelayFull) DecodeXDR(r io.Reader) error {
|
||||||
|
xr := xdr.NewReader(r)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RelayFull) UnmarshalXDR(bs []byte) error {
|
||||||
|
var br = bytes.NewReader(bs)
|
||||||
|
var xr = xdr.NewReader(br)
|
||||||
|
return o.DecodeXDRFrom(xr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RelayFull) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||||
|
return xr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
JoinSessionRequest Structure:
|
JoinSessionRequest Structure:
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
|
@ -50,6 +50,9 @@ func WriteMessage(w io.Writer, message interface{}) error {
|
|||||||
case SessionInvitation:
|
case SessionInvitation:
|
||||||
payload, err = msg.MarshalXDR()
|
payload, err = msg.MarshalXDR()
|
||||||
header.messageType = messageTypeSessionInvitation
|
header.messageType = messageTypeSessionInvitation
|
||||||
|
case RelayFull:
|
||||||
|
payload, err = msg.MarshalXDR()
|
||||||
|
header.messageType = messageTypeRelayFull
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("Unknown message type")
|
err = fmt.Errorf("Unknown message type")
|
||||||
}
|
}
|
||||||
@ -108,6 +111,10 @@ func ReadMessage(r io.Reader) (interface{}, error) {
|
|||||||
var msg SessionInvitation
|
var msg SessionInvitation
|
||||||
err := msg.DecodeXDR(r)
|
err := msg.DecodeXDR(r)
|
||||||
return msg, err
|
return msg, err
|
||||||
|
case messageTypeRelayFull:
|
||||||
|
var msg RelayFull
|
||||||
|
err := msg.DecodeXDR(r)
|
||||||
|
return msg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("Unknown message type")
|
return nil, fmt.Errorf("Unknown message type")
|
||||||
|
@ -12,20 +12,24 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/calmh/logger"
|
"github.com/syncthing/syncthing/lib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debug = strings.Contains(os.Getenv("STTRACE"), "locks") || os.Getenv("STTRACE") == "all"
|
|
||||||
threshold = time.Duration(100 * time.Millisecond)
|
threshold = time.Duration(100 * time.Millisecond)
|
||||||
l = logger.DefaultLogger
|
l = logger.DefaultLogger.NewFacility("sync", "Mutexes")
|
||||||
|
|
||||||
|
// We make an exception in this package and have an actual "if debug { ...
|
||||||
|
// }" variable, as it may be rather performance critical and does
|
||||||
|
// nonstandard things (from a debug logging PoV).
|
||||||
|
debug = strings.Contains(os.Getenv("STTRACE"), "sync") || os.Getenv("STTRACE") == "all"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if n, err := strconv.Atoi(os.Getenv("STLOCKTHRESHOLD")); debug && err == nil {
|
l.SetDebug("sync", strings.Contains(os.Getenv("STTRACE"), "sync") || os.Getenv("STTRACE") == "all")
|
||||||
|
|
||||||
|
if n, err := strconv.Atoi(os.Getenv("STLOCKTHRESHOLD")); err == nil {
|
||||||
threshold = time.Duration(n) * time.Millisecond
|
threshold = time.Duration(n) * time.Millisecond
|
||||||
}
|
}
|
||||||
if debug {
|
l.Debugf("Enabling lock logging at %v threshold", threshold)
|
||||||
l.Debugf("Enabling lock logging at %v threshold", threshold)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/calmh/logger"
|
"github.com/syncthing/syncthing/lib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -23,6 +23,7 @@ const (
|
|||||||
|
|
||||||
func TestTypes(t *testing.T) {
|
func TestTypes(t *testing.T) {
|
||||||
debug = false
|
debug = false
|
||||||
|
l.SetDebug("sync", false)
|
||||||
|
|
||||||
if _, ok := NewMutex().(*sync.Mutex); !ok {
|
if _, ok := NewMutex().(*sync.Mutex); !ok {
|
||||||
t.Error("Wrong type")
|
t.Error("Wrong type")
|
||||||
@ -37,6 +38,7 @@ func TestTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug = true
|
debug = true
|
||||||
|
l.SetDebug("sync", true)
|
||||||
|
|
||||||
if _, ok := NewMutex().(*loggedMutex); !ok {
|
if _, ok := NewMutex().(*loggedMutex); !ok {
|
||||||
t.Error("Wrong type")
|
t.Error("Wrong type")
|
||||||
@ -51,10 +53,12 @@ func TestTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
l.SetDebug("sync", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMutex(t *testing.T) {
|
func TestMutex(t *testing.T) {
|
||||||
debug = true
|
debug = true
|
||||||
|
l.SetDebug("sync", true)
|
||||||
threshold = logThreshold
|
threshold = logThreshold
|
||||||
|
|
||||||
msgmut := sync.Mutex{}
|
msgmut := sync.Mutex{}
|
||||||
@ -84,10 +88,12 @@ func TestMutex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
l.SetDebug("sync", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRWMutex(t *testing.T) {
|
func TestRWMutex(t *testing.T) {
|
||||||
debug = true
|
debug = true
|
||||||
|
l.SetDebug("sync", true)
|
||||||
threshold = logThreshold
|
threshold = logThreshold
|
||||||
|
|
||||||
msgmut := sync.Mutex{}
|
msgmut := sync.Mutex{}
|
||||||
@ -142,10 +148,12 @@ func TestRWMutex(t *testing.T) {
|
|||||||
mut.RUnlock()
|
mut.RUnlock()
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
l.SetDebug("sync", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWaitGroup(t *testing.T) {
|
func TestWaitGroup(t *testing.T) {
|
||||||
debug = true
|
debug = true
|
||||||
|
l.SetDebug("sync", true)
|
||||||
threshold = logThreshold
|
threshold = logThreshold
|
||||||
|
|
||||||
msgmut := sync.Mutex{}
|
msgmut := sync.Mutex{}
|
||||||
@ -182,4 +190,5 @@ func TestWaitGroup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
l.SetDebug("sync", false)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ var (
|
|||||||
getLimit time.Duration
|
getLimit time.Duration
|
||||||
postLimit time.Duration
|
postLimit time.Duration
|
||||||
permRelaysFile string
|
permRelaysFile string
|
||||||
ipHeader string
|
ipHeader string
|
||||||
|
|
||||||
getMut sync.RWMutex = sync.NewRWMutex()
|
getMut sync.RWMutex = sync.NewRWMutex()
|
||||||
getLRUCache *lru.Cache
|
getLRUCache *lru.Cache
|
||||||
@ -371,7 +371,7 @@ func requestProcessor() {
|
|||||||
if debug {
|
if debug {
|
||||||
log.Println("Request for", request.relay)
|
log.Println("Request for", request.relay)
|
||||||
}
|
}
|
||||||
if !client.TestRelay(request.uri, []tls.Certificate{testCert}, 250*time.Millisecond, 4) {
|
if !client.TestRelay(request.uri, []tls.Certificate{testCert}, time.Second, 2*time.Second, 3) {
|
||||||
if debug {
|
if debug {
|
||||||
log.Println("Test for relay", request.relay, "failed")
|
log.Println("Test for relay", request.relay, "failed")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user