diff --git a/application/application.go b/application/application.go index d48f92f..30a25c6 100644 --- a/application/application.go +++ b/application/application.go @@ -25,7 +25,6 @@ import ( pb "github.com/vishen/go-chromecast/cast/proto" "github.com/vishen/go-chromecast/playlists" "github.com/vishen/go-chromecast/storage" - "gopkg.in/ini.v1" "path/filepath" ) @@ -1427,12 +1426,3 @@ func (a *Application) Transcode(contentType string, command string, args ...stri a.MediaWait() return nil } - -// plsIterator is an iterator for playlist-files. -// According to https://en.wikipedia.org/wiki/PLS_(file_format), -// The format is case-sensitive and essentially that of an INI file. -// It has entries on the form File1, Title1 etc. -type plsIterator struct { - count int - playlist *ini.Section -} diff --git a/application/application_test.go b/application/application_test.go index 6e810a4..6d5b8f8 100644 --- a/application/application_test.go +++ b/application/application_test.go @@ -4,16 +4,12 @@ import ( "encoding/json" "testing" - "fmt" - "path/filepath" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/vishen/go-chromecast/application" "github.com/vishen/go-chromecast/cast" mockCast "github.com/vishen/go-chromecast/cast/mocks" pb "github.com/vishen/go-chromecast/cast/proto" - "github.com/vishen/go-chromecast/playlists" ) var mockAddr = "foo.bar" @@ -46,32 +42,3 @@ func TestApplicationStart(t *testing.T) { app := application.NewApplication(application.WithConnection(conn)) assertions.NoError(app.Start(mockAddr, mockPort)) } - -func TestParsePlaylist(t *testing.T) { - var path string - if abs, err := filepath.Abs(filepath.Join("..", "testdata", "indiepop64.pls")); err != nil { - t.Fatal(err) - } else { - path = fmt.Sprintf("file://%v", abs) - } - it, err := playlists.NewIterator(path) - if err != nil { - t.Fatal(err) - } - var wantUrls = []string{ - "https://ice4.somafm.com/indiepop-64-aac", - "https://ice2.somafm.com/indiepop-64-aac", - "https://ice1.somafm.com/indiepop-64-aac", - "https://ice6.somafm.com/indiepop-64-aac", - "https://ice5.somafm.com/indiepop-64-aac", - } - for i, want := range wantUrls { - if !it.HasNext() { - t.Fatal("iterator exhausted") - } - have, _ := it.Next() - if have != want { - t.Fatalf("url %d, have %v want %v", i, have, want) - } - } -} diff --git a/cmd/scan.go b/cmd/scan.go index 6ac5b59..b3bf4d8 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -20,10 +20,38 @@ import ( "sync" "time" + "encoding/json" "github.com/seancfoley/ipaddress-go/ipaddr" "github.com/spf13/cobra" + "io" + "net/http" ) +type deviceInfo struct { + Name string +} + +// getInfo uses the http://:8008/setup/eureka_endpoint to obtain more +// information about the cast-device. +// OBS: The 8008 seems to be pure http, whereas 8009 is typically the port +// to use for protobuf-communication +func getInfo(ip *ipaddr.IPAddress) (info *deviceInfo, err error) { + resp, err := http.Get(fmt.Sprintf("http://%v:8008/setup/eureka_info", ip)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + info = new(deviceInfo) + if err := json.Unmarshal(data, info); err != nil { + return nil, err + } + return info, nil +} + // scanCmd triggers a scan var scanCmd = &cobra.Command{ Use: "scan", @@ -33,7 +61,7 @@ var scanCmd = &cobra.Command{ cidrAddr, _ = cmd.Flags().GetString("cidr") port, _ = cmd.Flags().GetInt("port") wg sync.WaitGroup - uriCh = make(chan string) + ipCh = make(chan *ipaddr.IPAddress) logged = time.Unix(0, 0) start = time.Now() count int @@ -46,15 +74,15 @@ var scanCmd = &cobra.Command{ go func() { it := ipRange.Iterator() for it.HasNext() { - uri := fmt.Sprintf("%s:%d", it.Next(), port) + ip := it.Next() if time.Since(logged) > 8*time.Second { - outputInfo("Scanning... scanned %d, current %v\n", count, uri) + outputInfo("Scanning... scanned %d, current %v\n", count, ip.String()) logged = time.Now() } - uriCh <- uri + ipCh <- ip count++ } - close(uriCh) + close(ipCh) }() // Use a bunch of goroutines to do connect-attempts. for i := 0; i < 64; i++ { @@ -64,10 +92,16 @@ var scanCmd = &cobra.Command{ dialer := &net.Dialer{ Timeout: 400 * time.Millisecond, } - for uri := range uriCh { - if conn, err := dialer.Dial("tcp", uri); err == nil { - conn.Close() - outputInfo("Found (potential) chromecast at %v\n", uri) + for ip := range ipCh { + conn, err := dialer.Dial("tcp", fmt.Sprintf("%v:%d", ip, port)) + if err != nil { + continue + } + conn.Close() + if info, err := getInfo(ip); err != nil { + outputInfo(" - Device at %v:%d errored during discovery: %v", ip, port, err) + } else { + outputInfo(" - '%v' at %v:%d\n", info.Name, ip, port) } } }()