File: udp_proxy_linux_test.go

package info (click to toggle)
docker.io 28.5.2%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 69,048 kB
  • sloc: sh: 5,867; makefile: 863; ansic: 184; python: 162; asm: 159
file content (78 lines) | stat: -rw-r--r-- 1,907 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main

import (
	"net"
	"testing"
	"time"

	"gotest.tools/v3/assert"
)

// TestUDPOneSided makes sure that the conntrack entry isn't GC'd if the
// backend never writes to the UDP client.
func TestUDPOneSided(t *testing.T) {
	frontend, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
	assert.NilError(t, err)
	defer frontend.Close()

	backend, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
	assert.NilError(t, err)
	defer backend.Close()

	type udpMsg struct {
		data  []byte
		saddr *net.UDPAddr
	}
	msgs := make(chan udpMsg)
	go func() {
		for {
			buf := make([]byte, 1024)
			n, saddr, err := backend.ReadFromUDP(buf)
			if err != nil {
				return
			}
			msgs <- udpMsg{data: buf[:n], saddr: saddr}
		}
	}()

	proxy, err := NewUDPProxy(frontend, backend.LocalAddr().(*net.UDPAddr), ip4)
	assert.NilError(t, err)
	defer proxy.Close()

	const connTrackTimeout = 1 * time.Second
	proxy.connTrackTimeout = connTrackTimeout

	go func() {
		proxy.Run()
	}()

	client, err := net.DialUDP("udp", nil, frontend.LocalAddr().(*net.UDPAddr))
	assert.NilError(t, err)
	defer client.Close()

	var expSaddr *net.UDPAddr
	for i := range 15 {
		_, err = client.Write([]byte("hello"))
		assert.NilError(t, err)
		time.Sleep(100 * time.Millisecond)

		msg := <-msgs
		assert.Equal(t, string(msg.data), "hello")
		if i == 0 {
			expSaddr = msg.saddr
		} else {
			assert.Equal(t, msg.saddr.Port, expSaddr.Port)
		}
	}

	// The conntrack entry is checked every connTrackTimeout, but the latest
	// write might be less than connTrackTimeout ago. So we need to wait for
	// at least twice the conntrack timeout to make sure the entry is GC'd.
	time.Sleep(2 * connTrackTimeout)
	_, err = client.Write([]byte("hello"))
	assert.NilError(t, err)

	msg := <-msgs
	assert.Equal(t, string(msg.data), "hello")
	assert.Check(t, msg.saddr.Port != expSaddr.Port)
}