Skip to content

Commit 105c744

Browse files
Oppenanacrolix
authored andcommitted
feat: add IPv6 support for SSDP
This starts SSDP servers on IPv6 link-local and site-local addresses in addition to the original server for IPv4.
1 parent 0f6368a commit 105c744

File tree

2 files changed

+56
-25
lines changed

2 files changed

+56
-25
lines changed

dlna/dms/dms.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,23 +172,28 @@ const ssdpInterfaceFlags = net.FlagUp | net.FlagMulticast
172172
func (me *Server) doSSDP() {
173173
var wg sync.WaitGroup
174174
for _, if_ := range me.Interfaces {
175-
if_ := if_
176-
wg.Add(1)
177-
go func() {
178-
defer wg.Done()
179-
me.ssdpInterface(if_)
180-
}()
175+
for _, addr := range []string{ssdp.AddrString, ssdp.AddrString6LL, ssdp.AddrString6SL} {
176+
if_ := if_
177+
addr := addr
178+
wg.Add(1)
179+
go func() {
180+
defer wg.Done()
181+
me.ssdpInterface(if_, addr)
182+
}()
183+
}
181184
}
182185
wg.Wait()
183186
}
184187

185188
// Run SSDP server on an interface.
186-
func (me *Server) ssdpInterface(if_ net.Interface) {
189+
func (me *Server) ssdpInterface(if_ net.Interface, addrString string) {
187190
logger := me.Logger.WithNames("ssdp", if_.Name)
188191
s := ssdp.Server{
189-
Interface: if_,
190-
Devices: devices(),
191-
Services: serviceTypes(),
192+
Interface: if_,
193+
AddrString: addrString,
194+
NetAddr: ssdp.AddrString2NetAdd[addrString],
195+
Devices: devices(),
196+
Services: serviceTypes(),
192197
Location: func(ip net.IP) string {
193198
return me.location(ip)
194199
},

ssdp/ssdp.go

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,41 @@ import (
1515

1616
"github.com/anacrolix/log"
1717
"golang.org/x/net/ipv4"
18+
"golang.org/x/net/ipv6"
1819
)
1920

2021
const (
21-
AddrString = "239.255.255.250:1900"
22-
rootDevice = "upnp:rootdevice"
23-
aliveNTS = "ssdp:alive"
24-
byebyeNTS = "ssdp:byebye"
25-
mxMax = 10
22+
AddrString = "239.255.255.250:1900"
23+
AddrString6LL = "[ff02::c]:1900"
24+
AddrString6SL = "[ff05::c]:1900"
25+
rootDevice = "upnp:rootdevice"
26+
aliveNTS = "ssdp:alive"
27+
byebyeNTS = "ssdp:byebye"
28+
mxMax = 10
2629
)
2730

2831
var NetAddr *net.UDPAddr
32+
var NetAddr6LL *net.UDPAddr
33+
var NetAddr6SL *net.UDPAddr
34+
var AddrString2NetAdd map[string]*net.UDPAddr = make(map[string]*net.UDPAddr, 3)
2935

3036
func init() {
3137
var err error
3238
NetAddr, err = net.ResolveUDPAddr("udp4", AddrString)
3339
if err != nil {
3440
log.Printf("Could not resolve %s: %s", AddrString, err)
3541
}
42+
NetAddr6LL, err = net.ResolveUDPAddr("udp6", AddrString6LL)
43+
if err != nil {
44+
log.Printf("Could not resolve %s: %s", AddrString6LL, err)
45+
}
46+
NetAddr6SL, err = net.ResolveUDPAddr("udp6", AddrString6SL)
47+
if err != nil {
48+
log.Printf("Could not resolve %s: %s", AddrString6SL, err)
49+
}
50+
AddrString2NetAdd[AddrString] = NetAddr
51+
AddrString2NetAdd[AddrString6LL] = NetAddr6LL
52+
AddrString2NetAdd[AddrString6SL] = NetAddr6SL
3653
}
3754

3855
type badStringError struct {
@@ -81,6 +98,8 @@ func ReadRequest(b *bufio.Reader) (req *http.Request, err error) {
8198
type Server struct {
8299
conn *net.UDPConn
83100
Interface net.Interface
101+
AddrString string
102+
NetAddr *net.UDPAddr
84103
Server string
85104
Services []string
86105
Devices []string
@@ -92,14 +111,21 @@ type Server struct {
92111
Logger log.Logger
93112
}
94113

95-
func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) {
96-
ret, err = net.ListenMulticastUDP("udp", &ifi, NetAddr)
114+
func makeConn(ifi net.Interface, netAddr *net.UDPAddr) (ret *net.UDPConn, err error) {
115+
ret, err = net.ListenMulticastUDP("udp", &ifi, netAddr)
97116
if err != nil {
98117
return
99118
}
100-
p := ipv4.NewPacketConn(ret)
101-
if err := p.SetMulticastTTL(2); err != nil {
102-
log.Print(err)
119+
if netAddr.IP.String() == AddrString {
120+
p := ipv4.NewPacketConn(ret)
121+
if err := p.SetMulticastTTL(2); err != nil {
122+
log.Print(err)
123+
}
124+
} else {
125+
p := ipv6.NewPacketConn(ret)
126+
if err := p.SetMulticastHopLimit(2); err != nil {
127+
log.Print(err)
128+
}
103129
}
104130
// if err := p.SetMulticastLoopback(true); err != nil {
105131
// log.Println(err)
@@ -132,7 +158,7 @@ func (me *Server) serve() {
132158

133159
func (me *Server) Init() (err error) {
134160
me.closed = make(chan struct{})
135-
me.conn, err = makeConn(me.Interface)
161+
me.conn, err = makeConn(me.Interface, me.NetAddr)
136162
if me.IPFilter == nil {
137163
me.IPFilter = func(net.IP) bool { return true }
138164
}
@@ -195,7 +221,7 @@ func (me *Server) usnFromTarget(target string) string {
195221

196222
func (me *Server) makeNotifyMessage(target, nts string, extraHdrs [][2]string) []byte {
197223
lines := [...][2]string{
198-
{"HOST", AddrString},
224+
{"HOST", me.AddrString},
199225
{"NT", target},
200226
{"NTS", nts},
201227
{"SERVER", me.Server},
@@ -246,15 +272,15 @@ func (me *Server) log(args ...interface{}) {
246272
func (me *Server) sendByeBye() {
247273
for _, type_ := range me.allTypes() {
248274
buf := me.makeNotifyMessage(type_, byebyeNTS, nil)
249-
me.send(buf, NetAddr)
275+
me.send(buf, me.NetAddr)
250276
}
251277
}
252278

253279
func (me *Server) notifyAll(nts string, extraHdrs [][2]string) {
254280
for _, type_ := range me.allTypes() {
255281
buf := me.makeNotifyMessage(type_, nts, extraHdrs)
256282
delay := time.Duration(rand.Int63n(int64(100 * time.Millisecond)))
257-
me.delayedSend(delay, buf, NetAddr)
283+
me.delayedSend(delay, buf, me.NetAddr)
258284
}
259285
}
260286

@@ -279,7 +305,7 @@ func (me *Server) handle(buf []byte, sender *net.UDPAddr) {
279305
return
280306
}
281307
var mx int64
282-
if req.Header.Get("Host") == AddrString {
308+
if req.Header.Get("Host") == me.AddrString {
283309
mxHeader := req.Header.Get("mx")
284310
i, err := strconv.ParseUint(mxHeader, 0, 0)
285311
if err != nil {

0 commit comments

Comments
 (0)