Skip to content

Instantly share code, notes, and snippets.

@marten-seemann
Last active May 8, 2024 04:28
Show Gist options
  • Save marten-seemann/bfa811133331b9c053137fd5df12638d to your computer and use it in GitHub Desktop.
Save marten-seemann/bfa811133331b9c053137fd5df12638d to your computer and use it in GitHub Desktop.
package udp_test
import (
"crypto/rand"
"log"
"net"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestUDPUnconnectedDualStack(t *testing.T) {
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
require.NoError(t, err)
defer conn.Close()
done := make(chan struct{})
go func() {
defer close(done)
b := make([]byte, 1000)
n, addr, err := conn.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
t.Logf("received %d bytes from %s", n, addr)
}()
c, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
require.NoError(t, err)
defer c.Close()
b := make([]byte, 1000)
rand.Read(b)
t.Logf("sending packet from %s to %s", c.LocalAddr(), conn.LocalAddr())
_, err = c.WriteTo(b, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: conn.LocalAddr().(*net.UDPAddr).Port})
require.NoError(t, err)
select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("timeout")
}
}
func TestUDPUnconnectedDualStackWithRetransmission(t *testing.T) {
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
require.NoError(t, err)
defer conn.Close()
done := make(chan struct{})
go func() {
defer close(done)
b := make([]byte, 1000)
n, addr, err := conn.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
t.Logf("received %d bytes from %s", n, addr)
}()
c, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
require.NoError(t, err)
defer c.Close()
b := make([]byte, 1000)
rand.Read(b)
t.Logf("sending packet from %s to %s", c.LocalAddr(), conn.LocalAddr())
_, err = c.WriteTo(b, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: conn.LocalAddr().(*net.UDPAddr).Port})
require.NoError(t, err)
globalTimeout := time.After(5 * time.Second)
ticker := time.NewTicker(100 * time.Millisecond)
for {
select {
case <-done:
return
case <-ticker.C:
// send a retransmission
_, err = c.WriteTo(b, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: conn.LocalAddr().(*net.UDPAddr).Port})
require.NoError(t, err)
case <-globalTimeout:
t.Fatal("timeout")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment