Przeglądaj źródła

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
Jakob Borg 9 lat temu
rodzic
commit
f294113d01
1 zmienionych plików z 126 dodań i 0 usunięć
  1. 126 0
      cmd/stdisco/main.go

+ 126 - 0
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[:]
+}