// Copyright (C) 2016 The Syncthing Authors. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. package main import ( "crypto/rand" "encoding/binary" "flag" "log" "strings" "time" "github.com/syncthing/syncthing/lib/beacon" "github.com/syncthing/syncthing/lib/discover" "github.com/syncthing/syncthing/lib/protocol" ) var ( all = false // print all packets, not just first from each device/source fake = false // send fake packets to lure out other devices faster mc = "[ff12::8384]:21027" bc = 21027 ) var ( // Static prefix that we use when generating fake device IDs, so that we // can recognize them ourselves. Also makes the device ID start with // "STPROBE-" which is humanly recognizable. randomPrefix = []byte{148, 223, 23, 4, 148} // Our random, fake, device ID that we use when sending announcements. myID = randomDeviceID() ) func main() { flag.BoolVar(&all, "all", all, "Print all received announcements (not only first)") flag.BoolVar(&fake, "fake", fake, "Send fake announcements") flag.StringVar(&mc, "mc", mc, "IPv6 multicast address") flag.IntVar(&bc, "bc", bc, "IPv4 broadcast port number") flag.Parse() if fake { log.Println("My ID:", myID) } runbeacon(beacon.NewMulticast(mc), fake) runbeacon(beacon.NewBroadcast(bc), fake) select {} } func runbeacon(bc beacon.Interface, fake bool) { go bc.Serve() go recv(bc) if fake { go send(bc) } } // receives and prints discovery announcements func recv(bc beacon.Interface) { seen := make(map[string]bool) for { data, src := bc.Recv() if m := binary.BigEndian.Uint32(data); m != discover.Magic { log.Printf("Incorrect magic %x in announcement from %v", m, src) continue } var ann discover.Announce ann.Unmarshal(data[4:]) if ann.ID == myID { // This is one of our own fake packets, don't print it. continue } // Print announcement details for the first packet from a given // device ID and source address, or if -all was given. key := ann.ID.String() + src.String() if all || !seen[key] { log.Printf("Announcement from %v\n", src) log.Printf(" %v at %s\n", ann.ID, strings.Join(ann.Addresses, ", ")) seen[key] = true } } } // sends fake discovery announcements once every second func send(bc beacon.Interface) { ann := discover.Announce{ ID: myID, Addresses: []string{"tcp://fake.example.com:12345"}, } bs, _ := ann.Marshal() for { bc.Send(bs) time.Sleep(time.Second) } } // returns a random but recognizable device ID func randomDeviceID() protocol.DeviceID { var id protocol.DeviceID copy(id[:], randomPrefix) rand.Read(id[len(randomPrefix):]) return id }