mirror of
https://github.com/golang/go
synced 2024-11-21 21:44:40 -07:00
net: add IPv4 multicast to UDPConn
notes: Darwin is very particular about joining a multicast group if the listneing socket is not created in "udp4" mode, the other supported OS's are more flexible. A simple example sets up a socket to listen on the mdns/bonjour group 224.0.0.251:5353 // ensure the sock is udp4, and the IP is a 4 byte IPv4 socket, err := net.ListenUDP("udp4", &net.UDPAddr { IP: net.IPv4zero, // currently darwin will not allow you to bind to // a port if it is already bound to another process Port: 5353, }) if err != nil { log.Exitf("listen %s", err) } defer socket.Close() err = socket.JoinGroup(net.IPv4(224, 0, 0, 251)) if err != nil { log.Exitf("join group %s", err) } R=adg, rsc CC=golang-dev https://golang.org/cl/4066044
This commit is contained in:
parent
9b66129fe3
commit
0856731daa
56
src/pkg/net/multicast_test.go
Normal file
56
src/pkg/net/multicast_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMulticastJoinAndLeave(t *testing.T) {
|
||||
addr := &UDPAddr{
|
||||
IP: IPv4zero,
|
||||
Port: 0,
|
||||
}
|
||||
// open a UDPConn
|
||||
conn, err := ListenUDP("udp4", addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// try to join group
|
||||
mcast := IPv4(224, 0, 0, 251)
|
||||
err = conn.JoinGroup(mcast)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// try to leave group
|
||||
err = conn.LeaveGroup(mcast)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinFailureWithIPv6Address(t *testing.T) {
|
||||
addr := &UDPAddr{
|
||||
IP: IPv4zero,
|
||||
Port: 0,
|
||||
}
|
||||
|
||||
// open a UDPConn
|
||||
conn, err := ListenUDP("udp4", addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
// try to join group
|
||||
mcast := ParseIP("ff02::1")
|
||||
err = conn.JoinGroup(mcast)
|
||||
if err == nil {
|
||||
t.Fatal("JoinGroup succeeded, should fail")
|
||||
}
|
||||
t.Logf("%s", err)
|
||||
}
|
@ -279,3 +279,44 @@ func (c *UDPConn) BindToDevice(device string) os.Error {
|
||||
// It is the caller's responsibility to close f when finished.
|
||||
// Closing c does not affect f, and closing f does not affect c.
|
||||
func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
|
||||
|
||||
var errInvalidMulticast = os.ErrorString("invalid IPv4 multicast address")
|
||||
|
||||
// JoinGroup joins the IPv4 multicast group named by addr.
|
||||
// The UDPConn must use the "udp4" network.
|
||||
func (c *UDPConn) JoinGroup(addr IP) os.Error {
|
||||
if !c.ok() {
|
||||
return os.EINVAL
|
||||
}
|
||||
ip := addr.To4()
|
||||
if ip == nil {
|
||||
return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast}
|
||||
}
|
||||
mreq := &syscall.IpMreq{
|
||||
Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
|
||||
}
|
||||
err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
|
||||
if err != nil {
|
||||
return &OpError{"joingroup", "udp", &IPAddr{ip}, err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LeaveGroup exits the IPv4 multicast group named by addr.
|
||||
func (c *UDPConn) LeaveGroup(addr IP) os.Error {
|
||||
if !c.ok() {
|
||||
return os.EINVAL
|
||||
}
|
||||
ip := addr.To4()
|
||||
if ip == nil {
|
||||
return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast}
|
||||
}
|
||||
mreq := &syscall.IpMreq{
|
||||
Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
|
||||
}
|
||||
err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
|
||||
if err != nil {
|
||||
return &OpError{"leavegroup", "udp", &IPAddr{ip}, err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user