From 986907ad1a1c0dfa1e19dd5bdc88b6a14e9439ac Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Thu, 2 May 2019 11:23:58 +0200 Subject: [PATCH] Fix issue where starting a stream was aborted We now determine at which interface the client established a connection. We then determine the local ip address at that interface and respond accordingly. --- setup.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/setup.go b/setup.go index ff57f10..d1509bb 100644 --- a/setup.go +++ b/setup.go @@ -8,6 +8,7 @@ import ( "github.com/brutella/hc/service" "github.com/brutella/hc/tlv8" "net" + "reflect" "github.com/brutella/hkcam/ffmpeg" ) @@ -89,14 +90,8 @@ func setupStreamManagement(m *service.CameraRTPStreamManagement, ff ffmpeg.FFMPE log.Debug.Printf("%+v\n", req) - // respond with the IP address to which the request was sent to - ip := conn.LocalAddr().(*net.TCPAddr).IP - var ipVersion = rtp.IPAddrVersionv4 - if ip.To4() == nil { - ipVersion = rtp.IPAddrVersionv6 - } - - if ipVersion != req.ControllerAddr.IPVersion { + ip := localIPForConnection(conn, req.ControllerAddr.IPVersion) + if ip == nil { log.Info.Println("No IP version", req.ControllerAddr.IPVersion) return } @@ -109,7 +104,7 @@ func setupStreamManagement(m *service.CameraRTPStreamManagement, ff ffmpeg.FFMPE SessionId: req.SessionId, Status: rtp.SessionStatusSuccess, AccessoryAddr: rtp.Addr{ - IPVersion: ipVersion, + IPVersion: req.ControllerAddr.IPVersion, IPAddr: ip.String(), VideoRtpPort: req.ControllerAddr.VideoRtpPort, AudioRtpPort: req.ControllerAddr.AudioRtpPort, @@ -129,6 +124,60 @@ func setupStreamManagement(m *service.CameraRTPStreamManagement, ff ffmpeg.FFMPE }) } +// localIPForConnection returns the ip address of the interface at which the connection was established. +func localIPForConnection(conn net.Conn, version uint8) net.IP { + host, _, err := net.SplitHostPort(conn.LocalAddr().String()) + if err != nil { + log.Debug.Println(err) + return nil + } + + ip := net.ParseIP(host) + if ip == nil { + log.Debug.Println("unable to parse ip", host) + return nil + } + + ifaces, err := net.Interfaces() + if err != nil { + log.Debug.Println(err) + return nil + } + + for _, iface := range ifaces { + addrs, err := iface.Addrs() + if err != nil { + continue + } + + for _, addr := range addrs { + addrIP, _, err := net.ParseCIDR(addr.String()) + if err != nil { + log.Debug.Println(err) + continue + } + + log.Debug.Printf("%+v == %+v\n", addrIP, ip) + if reflect.DeepEqual(addrIP, ip) { + switch version { + case rtp.IPAddrVersionv4: + if ip.To4() != nil { + return ip + } + case rtp.IPAddrVersionv6: + if ip.To16() != nil { + return ip + } + default: + break + } + } + } + } + + return nil +} + func setTLV8Payload(c *characteristic.Bytes, v interface{}) { if tlv8, err := tlv8.Marshal(v); err == nil { c.SetValue(tlv8)