Skip to content

Commit

Permalink
Use golang.org/x/net/ipv4 to receive multicast messages in ssl-multic…
Browse files Browse the repository at this point in the history
…ast-sources

With the previous approach, message from different interfaces were received by all interfaces. With the higher level net/ipv4, suggested by the GO documentation, this can be done in a more sane way.
  • Loading branch information
g3force committed Mar 24, 2024
1 parent bf8fe41 commit 50349f4
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 28 deletions.
70 changes: 42 additions & 28 deletions cmd/ssl-multicast-sources/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ package main

import (
"flag"
"golang.org/x/net/ipv4"
"log"
"net"
"os"
"os/signal"
"strings"
"sync"
"syscall"
)

const maxDatagramSize = 8192

type Source struct {
nif string
ip string
port int
cm string
src string
}

var detectedRemotes map[string][]Source
Expand All @@ -30,11 +31,8 @@ func main() {
mcAddresses = []string{"224.5.23.1:10003", "224.5.23.2:10006", "224.5.23.2:10010", "224.5.23.2:10012"}
}

ifiList := interfaces()
for _, address := range mcAddresses {
for _, ifi := range ifiList {
go receiveOnInterface(address, ifi)
}
go receiveOnInterfaceIpv4(address)
}

signals := make(chan os.Signal, 1)
Expand All @@ -54,38 +52,54 @@ func interfaces() (interfaces []net.Interface) {
return
}

func receiveOnInterface(address string, ifi net.Interface) {
addr, err := net.ResolveUDPAddr("udp", address)
func receiveOnInterfaceIpv4(address string) {
group := net.ParseIP(strings.Split(address, ":")[0])
c, err := net.ListenPacket("udp4", address)
if err != nil {
log.Printf("Could resolve multicast address %v: %v", address, err)
log.Printf("Could not start listening on %v: %v", address, err)
return
}
defer func(c net.PacketConn) {
if err := c.Close(); err != nil {
log.Println("Failed to close connection:", err)
}
}(c)

conn, err := net.ListenMulticastUDP("udp", &ifi, addr)
if err != nil {
log.Printf("Could not listen at %v: %v", address, err)
return
}
log.Printf("Listening on %s", address)

p := ipv4.NewPacketConn(c)

if err := conn.SetReadBuffer(maxDatagramSize); err != nil {
log.Println("Could not set read buffer: ", err)
if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
log.Println("Failed to set control message flag 'FlagDst':", err)
}

log.Printf("Listening on %s (%s)", address, ifi.Name)
ifiList := interfaces()
for _, ifi := range ifiList {
if err := p.JoinGroup(&ifi, &net.UDPAddr{IP: group}); err != nil {
log.Printf("Failed to join multicast group %v: %v", group, err)
} else {
log.Printf("Joined multicast group %v on interface %+v", group, ifi)
}
}

data := make([]byte, maxDatagramSize)
for {
_, remoteAddr, err := conn.ReadFromUDP(data)
_, cm, src, err := p.ReadFrom(data)
if err != nil {
log.Println("ReadFromUDP failed:", err)
return
log.Printf("Could not read from %v: %v", address, err)
continue
}
if cm.Dst.IsMulticast() {
if cm.Dst.Equal(group) {
addRemote(address, Source{
cm: cm.String(),
src: src.String(),
})
} else {
// unknown group, discard
continue
}
}

addRemote(address, Source{
nif: ifi.Name,
ip: remoteAddr.IP.String(),
port: remoteAddr.Port,
})
}
}

Expand All @@ -104,5 +118,5 @@ func addRemote(address string, source Source) {
}

detectedRemotes[address] = append(detectedRemotes[address], source)
log.Printf("New source on %v: %+v\n", address, source)
log.Printf("New source on %v: %+v", address, source)
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ require (
github.com/pkg/errors v0.9.1
google.golang.org/protobuf v1.33.0
)

require (
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down

0 comments on commit 50349f4

Please sign in to comment.