Skip to content

Instantly share code, notes, and snippets.

@marten-seemann
Created August 5, 2020 06:14
Show Gist options
  • Save marten-seemann/74fa3cc3e7cd8dde76ec1ed18f6d7b31 to your computer and use it in GitHub Desktop.
Save marten-seemann/74fa3cc3e7cd8dde76ec1ed18f6d7b31 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/binary"
"fmt"
"log"
"net"
"syscall"
"time"
)
func main() {
addrChan := make(chan *net.UDPAddr)
go func() {
log.Fatal(runServer(addrChan))
}()
if err := runClient(<-addrChan); err != nil {
log.Fatal(err)
}
}
func setSockOpt(conn *net.UDPConn) error {
rawConn, err := conn.SyscallConn()
if err != nil {
return err
}
return rawConn.Control(func(fd uintptr) {
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
panic(err)
}
})
}
func runServer(addrChan chan<- *net.UDPAddr) error {
laddr, err := net.ResolveUDPAddr("udp4", "localhost:0")
if err != nil {
return err
}
conn, err := net.ListenUDP("udp4", laddr)
if err != nil {
return err
}
if err := setSockOpt(conn); err != nil {
return err
}
addrChan <- conn.LocalAddr().(*net.UDPAddr)
for {
b := make([]byte, 1000)
oob := make([]byte, 0, 1000)
n, oobn, flags, addr, err := conn.ReadMsgUDP(b, oob)
if err != nil {
return err
}
fmt.Println("Received packet:")
fmt.Printf("\tn: %d, oobn: %d, flags: %d, addr: %s\n", n, oobn, flags, addr)
fmt.Printf("\toob: %#x\n", oob[:oobn])
}
}
func runClient(raddr *net.UDPAddr) error {
laddr, err := net.ResolveUDPAddr("udp4", "localhost:0")
if err != nil {
return err
}
conn, err := net.ListenUDP("udp4", laddr)
if err != nil {
return err
}
if err := setSockOpt(conn); err != nil {
return err
}
for i := 0; i < 5; i++ {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(i))
if _, _, err := conn.WriteMsgUDP(b, nil, raddr); err != nil {
return err
}
time.Sleep(200 * time.Millisecond)
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment