main.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (C) 2016 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package main
  7. import (
  8. "bytes"
  9. "crypto/rand"
  10. "encoding/binary"
  11. "flag"
  12. "log"
  13. "strings"
  14. "time"
  15. "github.com/syncthing/syncthing/lib/beacon"
  16. "github.com/syncthing/syncthing/lib/discover"
  17. "github.com/syncthing/syncthing/lib/protocol"
  18. )
  19. var (
  20. all = false // print all packets, not just first from each device/source
  21. fake = false // send fake packets to lure out other devices faster
  22. mc = "[ff12::8384]:21027"
  23. bc = 21027
  24. )
  25. var (
  26. // Static prefix that we use when generating fake device IDs, so that we
  27. // can recognize them ourselves. Also makes the device ID start with
  28. // "STPROBE-" which is humanly recognizable.
  29. randomPrefix = []byte{148, 223, 23, 4, 148}
  30. // Our random, fake, device ID that we use when sending announcements.
  31. myID = randomDeviceID()
  32. )
  33. func main() {
  34. flag.BoolVar(&all, "all", all, "Print all received announcements (not only first)")
  35. flag.BoolVar(&fake, "fake", fake, "Send fake announcements")
  36. flag.StringVar(&mc, "mc", mc, "IPv6 multicast address")
  37. flag.IntVar(&bc, "bc", bc, "IPv4 broadcast port number")
  38. flag.Parse()
  39. if fake {
  40. log.Println("My ID:", protocol.DeviceIDFromBytes(myID))
  41. }
  42. runbeacon(beacon.NewMulticast(mc), fake)
  43. runbeacon(beacon.NewBroadcast(bc), fake)
  44. select {}
  45. }
  46. func runbeacon(bc beacon.Interface, fake bool) {
  47. go bc.Serve()
  48. go recv(bc)
  49. if fake {
  50. go send(bc)
  51. }
  52. }
  53. // receives and prints discovery announcements
  54. func recv(bc beacon.Interface) {
  55. seen := make(map[string]bool)
  56. for {
  57. data, src := bc.Recv()
  58. if m := binary.BigEndian.Uint32(data); m != discover.Magic {
  59. log.Printf("Incorrect magic %x in announcement from %v", m, src)
  60. continue
  61. }
  62. var ann discover.Announce
  63. ann.Unmarshal(data[4:])
  64. if bytes.Equal(ann.ID, myID) {
  65. // This is one of our own fake packets, don't print it.
  66. continue
  67. }
  68. // Print announcement details for the first packet from a given
  69. // device ID and source address, or if -all was given.
  70. key := string(ann.ID) + src.String()
  71. if all || !seen[key] {
  72. log.Printf("Announcement from %v\n", src)
  73. log.Printf(" %v at %s\n", protocol.DeviceIDFromBytes(ann.ID), strings.Join(ann.Addresses, ", "))
  74. seen[key] = true
  75. }
  76. }
  77. }
  78. // sends fake discovery announcements once every second
  79. func send(bc beacon.Interface) {
  80. ann := discover.Announce{
  81. ID: myID,
  82. Addresses: []string{"tcp://fake.example.com:12345"},
  83. }
  84. bs, _ := ann.Marshal()
  85. for {
  86. bc.Send(bs)
  87. time.Sleep(time.Second)
  88. }
  89. }
  90. // returns a random but recognizable device ID
  91. func randomDeviceID() []byte {
  92. var id [32]byte
  93. copy(id[:], randomPrefix)
  94. rand.Read(id[len(randomPrefix):])
  95. return id[:]
  96. }