Skip to content

Commit

Permalink
Merge pull request #39 from koron/ttl-configurable-31
Browse files Browse the repository at this point in the history
multicast: Configurable TTL and System assigned interface
  • Loading branch information
koron authored Oct 21, 2023
2 parents 77efa20 + 4a8d388 commit 92b1d6d
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 72 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.exe
*~
default.pgo
tags
tmp/
32 changes: 7 additions & 25 deletions advertise.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ type Advertiser struct {

// Advertise starts advertisement of service.
// location should be a string or a ssdp.LocationProvider.
func Advertise(st, usn string, location interface{}, server string, maxAge int, opts ...AdvertiserOption) (*Advertiser, error) {
func Advertise(st, usn string, location interface{}, server string, maxAge int, opts ...Option) (*Advertiser, error) {
locProv, err := toLocationProvider(location)
if err != nil {
return nil, err
}
conn, err := multicast.Listen(multicast.RecvAddrResolver)
cfg, err := opts2config(opts)
if err != nil {
return nil, err
}
conn, err := multicast.Listen(multicast.RecvAddrResolver, cfg.multicastConfig.options()...)
if err != nil {
return nil, err
}
Expand All @@ -57,9 +61,7 @@ func Advertise(st, usn string, location interface{}, server string, maxAge int,
maxAge: maxAge,
conn: conn,
ch: make(chan *message),
}
for _, o := range opts {
o.apply(a)
addHost: cfg.advertiseConfig.addHost,
}
a.wg.Add(2)
a.wgS.Add(1)
Expand Down Expand Up @@ -202,23 +204,3 @@ func (a *Advertiser) Bye() error {
ssdplog.Printf("sent bye")
return nil
}

// AdvertiserOption configures for specific behavior of Advertiser.
type AdvertiserOption interface {
apply(*Advertiser)
}

type advertiserOptionFunc func(*Advertiser)

func (af advertiserOptionFunc) apply(a *Advertiser) {
af(a)
}

// AdvertiserOptionAddHost returns as AdvertiserOption that add HOST header
// response for M-SEARCH request. This is added to support SmartThings.
// See https://github.com/koron/go-ssdp/issues/30 for details.
func AdvertiserOptionAddHost() AdvertiserOption {
return advertiserOptionFunc(func(a *Advertiser) {
a.addHost = true
})
}
16 changes: 12 additions & 4 deletions announce.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import (

// AnnounceAlive sends ssdp:alive message.
// location should be a string or a ssdp.LocationProvider.
func AnnounceAlive(nt, usn string, location interface{}, server string, maxAge int, localAddr string) error {
func AnnounceAlive(nt, usn string, location interface{}, server string, maxAge int, localAddr string, opts ...Option) error {
locProv, err := toLocationProvider(location)
if err != nil {
return err
}
cfg, err := opts2config(opts)
if err != nil {
return err
}
// dial multicast UDP packet.
conn, err := multicast.Listen(&multicast.AddrResolver{Addr: localAddr})
conn, err := multicast.Listen(&multicast.AddrResolver{Addr: localAddr}, cfg.multicastConfig.options()...)
if err != nil {
return err
}
Expand Down Expand Up @@ -75,9 +79,13 @@ func buildAlive(raddr net.Addr, nt, usn, location, server string, maxAge int) []
}

// AnnounceBye sends ssdp:byebye message.
func AnnounceBye(nt, usn, localAddr string) error {
func AnnounceBye(nt, usn, localAddr string, opts...Option) error {
cfg, err := opts2config(opts)
if err != nil {
return err
}
// dial multicast UDP packet.
conn, err := multicast.Listen(&multicast.AddrResolver{Addr: localAddr})
conn, err := multicast.Listen(&multicast.AddrResolver{Addr: localAddr}, cfg.multicastConfig.options()...)
if err != nil {
return err
}
Expand Down
12 changes: 11 additions & 1 deletion examples/advertise/advertise.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func main() {
srv := flag.String("srv", "", "SERVER: server header")
maxAge := flag.Int("maxage", 1800, "cache control, max-age")
ai := flag.Int("ai", 10, "alive interval")
ttl := flag.Int("ttl", 0, "TTL for outgoing multicast packets")
sysIf := flag.Bool("sysif", false, "use system assigned multicast interface")
v := flag.Bool("v", false, "verbose mode")
h := flag.Bool("h", false, "show help")
flag.Parse()
Expand All @@ -28,7 +30,15 @@ func main() {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
}

ad, err := ssdp.Advertise(*st, *usn, *loc, *srv, *maxAge)
var opts []ssdp.Option
if *ttl > 0 {
opts = append(opts, ssdp.TTL(*ttl))
}
if *sysIf {
opts = append(opts, ssdp.OnlySystemInterface())
}

ad, err := ssdp.Advertise(*st, *usn, *loc, *srv, *maxAge, opts...)
if err != nil {
log.Fatal(err)
}
Expand Down
12 changes: 11 additions & 1 deletion examples/alive/alive.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ func main() {
srv := flag.String("srv", "", "SERVER: server header")
maxAge := flag.Int("maxage", 1800, "cache control, max-age")
laddr := flag.String("laddr", "", "local address to listen")
ttl := flag.Int("ttl", 0, "TTL for outgoing multicast packets")
sysIf := flag.Bool("sysif", false, "use system assigned multicast interface")
v := flag.Bool("v", false, "verbose mode")
h := flag.Bool("h", false, "show help")
flag.Parse()
Expand All @@ -27,7 +29,15 @@ func main() {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
}

err := ssdp.AnnounceAlive(*nt, *usn, *loc, *srv, *maxAge, *laddr)
var opts []ssdp.Option
if *ttl > 0 {
opts = append(opts, ssdp.TTL(*ttl))
}
if *sysIf {
opts = append(opts, ssdp.OnlySystemInterface())
}

err := ssdp.AnnounceAlive(*nt, *usn, *loc, *srv, *maxAge, *laddr, opts...)
if err != nil {
log.Fatal(err)
}
Expand Down
12 changes: 11 additions & 1 deletion examples/bye/bye.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ func main() {
nt := flag.String("nt", "my:device", "NT: Type")
usn := flag.String("usn", "unique:id", "USN: ID")
laddr := flag.String("laddr", "", "local address to listen")
ttl := flag.Int("ttl", 0, "TTL for outgoing multicast packets")
sysIf := flag.Bool("sysif", false, "use system assigned multicast interface")
v := flag.Bool("v", false, "verbose mode")
h := flag.Bool("h", false, "show help")
flag.Parse()
Expand All @@ -24,7 +26,15 @@ func main() {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
}

err := ssdp.AnnounceBye(*nt, *usn, *laddr)
var opts []ssdp.Option
if *ttl > 0 {
opts = append(opts, ssdp.TTL(*ttl))
}
if *sysIf {
opts = append(opts, ssdp.OnlySystemInterface())
}

err := ssdp.AnnounceBye(*nt, *usn, *laddr, opts...)
if err != nil {
log.Fatal(err)
}
Expand Down
17 changes: 14 additions & 3 deletions examples/monitor/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func main() {
v := flag.Bool("v", false, "verbose mode")
h := flag.Bool("h", false, "show help")
flag.StringVar(&filterType, "filter_type", "", "print only a specified type (ST or NT). default is print all types.")
ttl := flag.Int("ttl", 0, "TTL for outgoing multicast packets")
sysIf := flag.Bool("sysif", false, "use system assigned multicast interface")
flag.Parse()

if *h {
Expand All @@ -24,10 +26,19 @@ func main() {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
}

var opts []ssdp.Option
if *ttl > 0 {
opts = append(opts, ssdp.TTL(*ttl))
}
if *sysIf {
opts = append(opts, ssdp.OnlySystemInterface())
}

m := &ssdp.Monitor{
Alive: onAlive,
Bye: onBye,
Search: onSearch,
Alive: onAlive,
Bye: onBye,
Search: onSearch,
Options: opts,
}
if err := m.Start(); err != nil {
log.Fatal(err)
Expand Down
13 changes: 12 additions & 1 deletion examples/search/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func main() {
t := flag.String("t", ssdp.All, "search type")
w := flag.Int("w", 1, "wait time")
l := flag.String("l", "", "local address to listen")
ttl := flag.Int("ttl", 0, "TTL for outgoing multicast packets")
sysIf := flag.Bool("sysif", false, "use system assigned multicast interface")
v := flag.Bool("v", false, "verbose mode")
h := flag.Bool("h", false, "show help")
flag.Parse()
Expand All @@ -23,7 +25,16 @@ func main() {
if *v {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
}
list, err := ssdp.Search(*t, *w, *l)

var opts []ssdp.Option
if *ttl > 0 {
opts = append(opts, ssdp.TTL(*ttl))
}
if *sysIf {
opts = append(opts, ssdp.OnlySystemInterface())
}

list, err := ssdp.Search(*t, *w, *l, opts...)
if err != nil {
log.Fatal(err)
}
Expand Down
4 changes: 4 additions & 0 deletions internal/multicast/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ type InterfacesProviderFunc func() []net.Interface
// If no provider are given, all possible interfaces will be used.
var InterfacesProvider InterfacesProviderFunc

// SystemAssignedInterface indicates use the system assigned multicast interface or not.
// InterfacesProvider will be ignored when this is true.
var SystemAssignedInterface bool = false

// interfaces gets list of net.Interface to multicast UDP packet.
func interfaces() ([]net.Interface, error) {
if p := InterfacesProvider; p != nil {
Expand Down
Loading

0 comments on commit 92b1d6d

Please sign in to comment.