-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
packetization_test.go
121 lines (110 loc) · 3.49 KB
/
packetization_test.go
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package self_test
import (
"context"
"fmt"
"net"
"time"
"github.com/lucas-clemente/quic-go"
quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy"
"github.com/lucas-clemente/quic-go/logging"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Packetization", func() {
// In this test, the client sends 100 small messages. The server echoes these messages.
// This means that every endpoint will send 100 ack-eliciting packets in short succession.
// This test then tests that no more than 110 packets are sent in every direction, making sure that ACK are bundled.
It("bundles ACKs", func() {
const numMsg = 100
serverTracer := newPacketTracer()
server, err := quic.ListenAddr(
"localhost:0",
getTLSConfig(),
getQuicConfig(&quic.Config{
DisablePathMTUDiscovery: true,
Tracer: newTracer(func() logging.ConnectionTracer { return serverTracer }),
}),
)
Expect(err).ToNot(HaveOccurred())
serverAddr := fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port)
defer server.Close()
proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{
RemoteAddr: serverAddr,
DelayPacket: func(dir quicproxy.Direction, _ []byte) time.Duration {
return 5 * time.Millisecond
},
})
Expect(err).ToNot(HaveOccurred())
defer proxy.Close()
clientTracer := newPacketTracer()
conn, err := quic.DialAddr(
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
getTLSClientConfig(),
getQuicConfig(&quic.Config{
DisablePathMTUDiscovery: true,
Tracer: newTracer(func() logging.ConnectionTracer { return clientTracer }),
}),
)
Expect(err).ToNot(HaveOccurred())
go func() {
defer GinkgoRecover()
conn, err := server.Accept(context.Background())
Expect(err).ToNot(HaveOccurred())
str, err := conn.AcceptStream(context.Background())
Expect(err).ToNot(HaveOccurred())
b := make([]byte, 1)
// Echo every byte received from the client.
for {
if _, err := str.Read(b); err != nil {
break
}
_, err = str.Write(b)
Expect(err).ToNot(HaveOccurred())
}
}()
str, err := conn.OpenStreamSync(context.Background())
Expect(err).ToNot(HaveOccurred())
b := make([]byte, 1)
// Send numMsg 1-byte messages.
for i := 0; i < numMsg; i++ {
_, err = str.Write([]byte{uint8(i)})
Expect(err).ToNot(HaveOccurred())
_, err = str.Read(b)
Expect(err).ToNot(HaveOccurred())
Expect(b[0]).To(Equal(uint8(i)))
}
Expect(conn.CloseWithError(0, "")).To(Succeed())
countBundledPackets := func(packets []packet) (numBundled int) {
for _, p := range packets {
if p.hdr.IsLongHeader {
continue
}
var hasAck, hasStreamFrame bool
for _, f := range p.frames {
switch f.(type) {
case *logging.AckFrame:
hasAck = true
case *logging.StreamFrame:
hasStreamFrame = true
}
}
if hasAck && hasStreamFrame {
numBundled++
}
}
return
}
numBundledIncoming := countBundledPackets(clientTracer.getRcvdPackets())
numBundledOutgoing := countBundledPackets(serverTracer.getRcvdPackets())
fmt.Fprintf(GinkgoWriter, "bundled incoming packets: %d / %d\n", numBundledIncoming, numMsg)
fmt.Fprintf(GinkgoWriter, "bundled outgoing packets: %d / %d\n", numBundledOutgoing, numMsg)
Expect(numBundledIncoming).To(And(
BeNumerically("<=", numMsg),
BeNumerically(">", numMsg*9/10),
))
Expect(numBundledOutgoing).To(And(
BeNumerically("<=", numMsg),
BeNumerically(">", numMsg*9/10),
))
})
})