@@ -22,6 +22,7 @@ type Conn struct {
22
22
23
23
type connConfig struct {
24
24
ttl int
25
+ sysIf bool
25
26
}
26
27
27
28
// Listen starts to receiving multicast messages.
@@ -42,16 +43,11 @@ func Listen(r *AddrResolver, opts ...ConnOption) (*Conn, error) {
42
43
return nil , err
43
44
}
44
45
// configure socket to use with multicast.
45
- pconn , iflist , err := newIPv4MulticastConn (conn )
46
+ pconn , ifplist , err := newIPv4MulticastConn (conn , cfg . sysIf )
46
47
if err != nil {
47
48
conn .Close ()
48
49
return nil , err
49
50
}
50
- // store interfaces by pointer.
51
- ifplist := make ([]* net.Interface , 0 , len (iflist ))
52
- for i := range iflist {
53
- ifplist = append (ifplist , & iflist [i ])
54
- }
55
51
// set TTL
56
52
if cfg .ttl > 0 {
57
53
err := pconn .SetTTL (cfg .ttl )
@@ -67,35 +63,58 @@ func Listen(r *AddrResolver, opts ...ConnOption) (*Conn, error) {
67
63
}, nil
68
64
}
69
65
70
- func newIPv4MulticastConn (conn * net.UDPConn ) (* ipv4.PacketConn , []net.Interface , error ) {
71
- iflist , err := interfaces ()
72
- if err != nil {
73
- return nil , nil , err
66
+ // newIPv4MulticastConn create a new multicast connection.
67
+ // 2nd return parameter will be nil when sysIf is true.
68
+ func newIPv4MulticastConn (conn * net.UDPConn , sysIf bool ) (* ipv4.PacketConn , []* net.Interface , error ) {
69
+ // sysIf: use system assigned multicast interface.
70
+ // the empty iflist indicate it.
71
+ var ifplist []* net.Interface
72
+ if ! sysIf {
73
+ list , err := interfaces ()
74
+ if err != nil {
75
+ return nil , nil , err
76
+ }
77
+ ifplist = make ([]* net.Interface , 0 , len (list ))
78
+ for i := range list {
79
+ ifplist = append (ifplist , & list [i ])
80
+ }
74
81
}
75
82
addr , err := SendAddr ()
76
83
if err != nil {
77
84
return nil , nil , err
78
85
}
79
- pconn , err := joinGroupIPv4 (conn , iflist , addr )
86
+ pconn , err := joinGroupIPv4 (conn , ifplist , addr )
80
87
if err != nil {
81
88
return nil , nil , err
82
89
}
83
- return pconn , iflist , nil
90
+ return pconn , ifplist , nil
84
91
}
85
92
86
93
// joinGroupIPv4 makes the connection join to a group on interfaces.
87
- func joinGroupIPv4 (conn * net.UDPConn , iflist []net.Interface , gaddr net.Addr ) (* ipv4.PacketConn , error ) {
94
+ // This trys to use system assigned when iflist is nil or empty.
95
+ func joinGroupIPv4 (conn * net.UDPConn , ifplist []* net.Interface , gaddr net.Addr ) (* ipv4.PacketConn , error ) {
88
96
wrap := ipv4 .NewPacketConn (conn )
89
97
wrap .SetMulticastLoopback (true )
98
+
99
+ // try to use the system assigned multicast interface when iflist is empty.
100
+ if len (ifplist ) == 0 {
101
+ if err := wrap .JoinGroup (nil , gaddr ); err != nil {
102
+ ssdplog .Printf ("failed to join group %s on system assigned multicast interface: %s" , gaddr .String (), err )
103
+ return nil , errors .New ("no system assigned multicast interfaces had joined to group" )
104
+ }
105
+ ssdplog .Printf ("joined group %s on system assigned multicast interface" , gaddr .String ())
106
+ return wrap , nil
107
+ }
108
+
90
109
// add interfaces to multicast group.
91
110
joined := 0
92
- for _ , ifi := range iflist {
93
- if err := wrap .JoinGroup (& ifi , gaddr ); err != nil {
94
- ssdplog .Printf ("failed to join group %s on %s: %s" , gaddr .String (), ifi .Name , err )
111
+ for _ , ifp := range ifplist {
112
+ if err := wrap .JoinGroup (ifp , gaddr ); err != nil {
113
+ ssdplog .Printf ("failed to join group %s on %s: %s" , gaddr .String (), ifp .Name , err )
95
114
continue
96
115
}
97
116
joined ++
98
- ssdplog .Printf ("joined group %s on %s (#%d)" , gaddr .String (), ifi .Name , ifi .Index )
117
+ ssdplog .Printf ("joined group %s on %s (#%d)" , gaddr .String (), ifp .Name , ifp .Index )
99
118
}
100
119
if joined == 0 {
101
120
return nil , errors .New ("no interfaces had joined to group" )
@@ -117,12 +136,6 @@ type DataProvider interface {
117
136
Bytes (* net.Interface ) []byte
118
137
}
119
138
120
- //type multicastDataProviderFunc func(*net.Interface) []byte
121
- //
122
- //func (f multicastDataProviderFunc) Bytes(ifi *net.Interface) []byte {
123
- // return f(ifi)
124
- //}
125
-
126
139
type BytesDataProvider []byte
127
140
128
141
func (b BytesDataProvider ) Bytes (ifi * net.Interface ) []byte {
@@ -131,9 +144,11 @@ func (b BytesDataProvider) Bytes(ifi *net.Interface) []byte {
131
144
132
145
// WriteTo sends a multicast message to interfaces.
133
146
func (mc * Conn ) WriteTo (dataProv DataProvider , to net.Addr ) (int , error ) {
147
+ // Send a multicast message directory when recipient "to" address is not multicast.
134
148
if uaddr , ok := to .(* net.UDPAddr ); ok && ! uaddr .IP .IsMulticast () {
135
149
return mc .writeToIfi (dataProv , to , nil )
136
150
}
151
+ // Send a multicast message to all interfaces (iflist).
137
152
sum := 0
138
153
for _ , ifp := range mc .ifps {
139
154
n , err := mc .writeToIfi (dataProv , to , ifp )
@@ -197,3 +212,9 @@ func ConnTTL(ttl int) ConnOption {
197
212
cfg .ttl = ttl
198
213
})
199
214
}
215
+
216
+ func ConnSystemAssginedInterface () ConnOption {
217
+ return connOptFunc (func (cfg * connConfig ) {
218
+ cfg .sysIf = true
219
+ })
220
+ }
0 commit comments