nasne を探す
239.255.255.250:1900 に multicast udp を投げる
- http request みたいな感じで method は
M-Search
, path は*
とする - response も以下のような request 形式で返ってくる
NOTIFY * HTTP/1.1 Host: 239.255.255.250:1900 User-Agent: Go 1.1 package http Cache-Control: max-age=1800 Location: http://x.x.x.x:58888/ Nt: urn:schemas-xsrs-org:service:X_ScheduledRecording:2 Nts: ssdp:alive Server: Linux/2.6 UPnP/1.0 nasne/1.0 Usn: uuid:xxxx::urn:schemas-xsrs-org:service:X_ScheduledRecording:2 X-Av-Server-Info: av="5.0"; hn=""; cn="Sony Computer Entertainment Inc.";mn="nasne";mv="1.0";
こういう request が出てきたら location の先にアクセスするとさらにどういうサービスが定義されてるかわかる。
package main import ( "bufio" "bytes" "log" "net" "net/http" ) func main() { if err := _main(); err != nil { log.Fatal(err) } } func _main() error { addr := &net.UDPAddr{ IP: net.ParseIP("239.255.255.250"), Port: 1900, } conn, err := net.ListenMulticastUDP("udp4", nil, addr) if err != nil { return err } defer conn.Close() req, err := http.NewRequest("M-Search", "*", nil) if err != nil { return err } req.Header.Set("ST", "upnp:rootdevice") req.Header.Set("MX", "10") req.Header.Set("MAN", `"ssdp:discover"`) var b bytes.Buffer if err := req.Write(&b); err != nil { return err } if _, err := conn.WriteToUDP(b.Bytes(), addr); err != nil { return err } for { req2, err := http.ReadRequest(bufio.NewReader((conn))) if err != nil { log.Println(err) break } log.Println(req2) } return nil }
- 適当なタイムアウトとかで for は抜けるようにする必要がある