main.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package main
  2. import (
  3. "crypto/tls"
  4. "flag"
  5. "io"
  6. "log"
  7. "os"
  8. "path/filepath"
  9. "github.com/calmh/syncthing/protocol"
  10. )
  11. var (
  12. exit bool
  13. cmd string
  14. confDir string
  15. target string
  16. get string
  17. pc protocol.Connection
  18. )
  19. func main() {
  20. log.SetFlags(0)
  21. log.SetOutput(os.Stdout)
  22. flag.StringVar(&cmd, "cmd", "idx", "Command")
  23. flag.StringVar(&confDir, "home", ".", "Certificates directory")
  24. flag.StringVar(&target, "target", "127.0.0.1:22000", "Target node")
  25. flag.StringVar(&get, "get", "", "Get file")
  26. flag.BoolVar(&exit, "exit", false, "Exit after command")
  27. flag.Parse()
  28. connect(target)
  29. select {}
  30. }
  31. func connect(target string) {
  32. cert, err := loadCert(confDir)
  33. if err != nil {
  34. log.Fatal(err)
  35. }
  36. myID := string(certID(cert.Certificate[0]))
  37. tlsCfg := &tls.Config{
  38. Certificates: []tls.Certificate{cert},
  39. NextProtos: []string{"bep/1.0"},
  40. ServerName: myID,
  41. ClientAuth: tls.RequestClientCert,
  42. SessionTicketsDisabled: true,
  43. InsecureSkipVerify: true,
  44. MinVersion: tls.VersionTLS12,
  45. }
  46. conn, err := tls.Dial("tcp", target, tlsCfg)
  47. if err != nil {
  48. log.Fatal(err)
  49. }
  50. remoteID := certID(conn.ConnectionState().PeerCertificates[0].Raw)
  51. pc = protocol.NewConnection(remoteID, conn, conn, Model{})
  52. select {}
  53. }
  54. type Model struct {
  55. }
  56. func prtIndex(files []protocol.FileInfo) {
  57. for _, f := range files {
  58. log.Printf("%q (v:%d mod:%d flags:0%o nblocks:%d)", f.Name, f.Version, f.Modified, f.Flags, len(f.Blocks))
  59. for _, b := range f.Blocks {
  60. log.Printf(" %6d %x", b.Size, b.Hash)
  61. }
  62. }
  63. }
  64. func (m Model) Index(nodeID string, repo string, files []protocol.FileInfo) {
  65. log.Printf("Received index for repo %q", repo)
  66. if cmd == "idx" {
  67. prtIndex(files)
  68. if get != "" {
  69. for _, f := range files {
  70. if f.Name == get {
  71. go getFile(f)
  72. break
  73. }
  74. }
  75. } else if exit {
  76. os.Exit(0)
  77. }
  78. }
  79. }
  80. func getFile(f protocol.FileInfo) {
  81. fn := filepath.Base(f.Name)
  82. fd, err := os.Create(fn)
  83. if err != nil {
  84. log.Fatal(err)
  85. }
  86. var offset int64
  87. for _, b := range f.Blocks {
  88. log.Printf("Request %q %d - %d", f.Name, offset, offset+int64(b.Size))
  89. bs, err := pc.Request("default", f.Name, offset, int(b.Size))
  90. log.Printf(" - got %d bytes", len(bs))
  91. if err != nil {
  92. log.Fatal(err)
  93. }
  94. offset += int64(b.Size)
  95. fd.Write(bs)
  96. }
  97. fd.Close()
  98. }
  99. func (m Model) IndexUpdate(nodeID string, repo string, files []protocol.FileInfo) {
  100. log.Printf("Received index update for repo %q", repo)
  101. if cmd == "idx" {
  102. prtIndex(files)
  103. if exit {
  104. os.Exit(0)
  105. }
  106. }
  107. }
  108. func (m Model) ClusterConfig(nodeID string, config protocol.ClusterConfigMessage) {
  109. log.Println("Received cluster config")
  110. log.Printf("%#v", config)
  111. }
  112. func (m Model) Request(nodeID, repo string, name string, offset int64, size int) ([]byte, error) {
  113. log.Println("Received request")
  114. return nil, io.EOF
  115. }
  116. func (m Model) Close(nodeID string, err error) {
  117. log.Println("Received close")
  118. }