From f294113d016db9135a88a6467d8ff50cc1d51b78 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 17 Apr 2016 18:47:38 +0000 Subject: [PATCH] cmd/stdisco: New utility to debug local discovery When run without parameters, attempts to listen for local discovery announcements just like Syncthing, and prints them. With -send, it also sends fake discovery packets. This can be used on two or more computers simultaneously to verify that they can see each other. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/2985 --- cmd/stdisco/main.go | 126 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 cmd/stdisco/main.go diff --git a/cmd/stdisco/main.go b/cmd/stdisco/main.go new file mode 100644 index 000000000..3b1d877c7 --- /dev/null +++ b/cmd/stdisco/main.go @@ -0,0 +1,126 @@ +// 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 http://mozilla.org/MPL/2.0/. + +package main + +import ( + "bytes" + "crypto/rand" + "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 recognizeable. + 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:", protocol.DeviceIDFromBytes(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() + var ann discover.Announce + ann.UnmarshalXDR(data) + + if bytes.Equal(ann.This.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 := string(ann.This.ID) + src.String() + if all || !seen[key] { + log.Printf("Announcement from %v\n", src) + log.Printf(" %v at %s\n", protocol.DeviceIDFromBytes(ann.This.ID), strings.Join(addrStrs(ann.This), ", ")) + + for _, dev := range ann.Extra { + log.Printf(" %v at %s\n", protocol.DeviceIDFromBytes(dev.ID), strings.Join(addrStrs(dev), ", ")) + } + seen[key] = true + } + } +} + +// sends fake discovery announcements once every second +func send(bc beacon.Interface) { + ann := discover.Announce{ + Magic: discover.AnnouncementMagic, + This: discover.Device{ + ID: myID, + Addresses: []discover.Address{ + {URL: "tcp://fake.example.com:12345"}, + }, + }, + } + bs, _ := ann.MarshalXDR() + + for { + bc.Send(bs) + time.Sleep(time.Second) + } +} + +// returns the list of address URLs +func addrStrs(dev discover.Device) []string { + ss := make([]string, len(dev.Addresses)) + for i, addr := range dev.Addresses { + ss[i] = addr.URL + } + return ss +} + +// returns a random but recognizeable device ID +func randomDeviceID() []byte { + var id [32]byte + copy(id[:], randomPrefix) + rand.Read(id[len(randomPrefix):]) + return id[:] +}