bep_extensions.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright (C) 2014 The Protocol Authors.
  2. //go:generate go run ../../script/protofmt.go bep.proto
  3. //go:generate protoc --proto_path=../../../../../:../../../../gogo/protobuf/protobuf:. --gogofast_out=. bep.proto
  4. package protocol
  5. import (
  6. "bytes"
  7. "crypto/sha256"
  8. "encoding/binary"
  9. "errors"
  10. "fmt"
  11. "time"
  12. "github.com/syncthing/syncthing/lib/rand"
  13. )
  14. var (
  15. sha256OfEmptyBlock = sha256.Sum256(make([]byte, BlockSize))
  16. HelloMessageMagic = uint32(0x2EA7D90B)
  17. )
  18. func (m Hello) Magic() uint32 {
  19. return HelloMessageMagic
  20. }
  21. func (f FileInfo) String() string {
  22. return fmt.Sprintf("File{Name:%q, Type:%v, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, Blocks:%v}",
  23. f.Name, f.Type, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.Blocks)
  24. }
  25. func (f FileInfo) IsDeleted() bool {
  26. return f.Deleted
  27. }
  28. func (f FileInfo) IsInvalid() bool {
  29. return f.Invalid
  30. }
  31. func (f FileInfo) IsDirectory() bool {
  32. return f.Type == FileInfoTypeDirectory
  33. }
  34. func (f FileInfo) IsSymlink() bool {
  35. switch f.Type {
  36. case FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile, FileInfoTypeSymlinkUnknown:
  37. return true
  38. default:
  39. return false
  40. }
  41. }
  42. func (f FileInfo) HasPermissionBits() bool {
  43. return !f.NoPermissions
  44. }
  45. func (f FileInfo) FileSize() int64 {
  46. if f.IsDirectory() || f.IsDeleted() {
  47. return 128
  48. }
  49. return f.Size
  50. }
  51. func (f FileInfo) FileName() string {
  52. return f.Name
  53. }
  54. func (f FileInfo) ModTime() time.Time {
  55. return time.Unix(f.ModifiedS, int64(f.ModifiedNs))
  56. }
  57. // WinsConflict returns true if "f" is the one to choose when it is in
  58. // conflict with "other".
  59. func (f FileInfo) WinsConflict(other FileInfo) bool {
  60. // If a modification is in conflict with a delete, we pick the
  61. // modification.
  62. if !f.IsDeleted() && other.IsDeleted() {
  63. return true
  64. }
  65. if f.IsDeleted() && !other.IsDeleted() {
  66. return false
  67. }
  68. // The one with the newer modification time wins.
  69. if f.ModTime().After(other.ModTime()) {
  70. return true
  71. }
  72. if f.ModTime().Before(other.ModTime()) {
  73. return false
  74. }
  75. // The modification times were equal. Use the device ID in the version
  76. // vector as tie breaker.
  77. return f.Version.Compare(other.Version) == ConcurrentGreater
  78. }
  79. func (b BlockInfo) String() string {
  80. return fmt.Sprintf("Block{%d/%d/%x}", b.Offset, b.Size, b.Hash)
  81. }
  82. // IsEmpty returns true if the block is a full block of zeroes.
  83. func (b BlockInfo) IsEmpty() bool {
  84. return b.Size == BlockSize && bytes.Equal(b.Hash, sha256OfEmptyBlock[:])
  85. }
  86. type IndexID uint64
  87. func (i IndexID) String() string {
  88. return fmt.Sprintf("0x%16X", uint64(i))
  89. }
  90. func (i IndexID) Marshal() ([]byte, error) {
  91. bs := make([]byte, 8)
  92. binary.BigEndian.PutUint64(bs, uint64(i))
  93. return bs, nil
  94. }
  95. func (i *IndexID) Unmarshal(bs []byte) error {
  96. if len(bs) != 8 {
  97. return errors.New("incorrect IndexID length")
  98. }
  99. *i = IndexID(binary.BigEndian.Uint64(bs))
  100. return nil
  101. }
  102. func NewIndexID() IndexID {
  103. return IndexID(rand.Int64())
  104. }