...
1
16
17 package nat
18
19
28
29 import (
30 "errors"
31 "io"
32 "log"
33 "net"
34 "time"
35
36 "k8s.io/kubernetes/test/images/agnhost/net/common"
37 )
38
39
40
41
42
43 var leakedConnection *net.TCPConn
44
45
46 type CloseWaitServerOptions struct {
47
48 LocalAddr string
49
50 PostFinTimeoutSeconds int
51 }
52
53 type closeWaitServer struct {
54 options *CloseWaitServerOptions
55 }
56
57
58 func NewCloseWaitServer() common.Runner {
59 return &closeWaitServer{}
60 }
61
62
63 func (server *closeWaitServer) NewOptions() interface{} {
64 return &CloseWaitServerOptions{}
65 }
66
67
68 func (server *closeWaitServer) Run(logger *log.Logger, rawOptions interface{}) error {
69 if options, ok := rawOptions.(*CloseWaitServerOptions); ok {
70 server.options = options
71 } else {
72 return errors.New("invalid type")
73 }
74
75 logger.Printf("Run %v", server.options)
76
77 addr, err := net.ResolveTCPAddr("tcp", server.options.LocalAddr)
78 if err != nil {
79 return err
80 }
81
82 listener, err := net.ListenTCP("tcp", addr)
83 if err != nil {
84 return err
85 }
86 defer listener.Close()
87
88 logger.Printf("Server listening on %v", addr)
89
90 conn, err := listener.AcceptTCP()
91 if err != nil {
92 return err
93 }
94 defer conn.Close()
95
96 logger.Printf("Client connected")
97
98
99
100
101 if err := conn.CloseWrite(); err != nil {
102 return err
103 }
104
105 logger.Printf("Server sent FIN, waiting %v seconds",
106 server.options.PostFinTimeoutSeconds)
107
108 <-time.After(time.Duration(server.options.PostFinTimeoutSeconds) * time.Second)
109
110 logger.Printf("Done")
111
112 return nil
113 }
114
115
116 type CloseWaitClientOptions struct {
117
118 RemoteAddr string
119
120 TimeoutSeconds int
121
122
123 PostFinTimeoutSeconds int
124
125
126 LeakConnection bool
127 }
128
129 type closeWaitClient struct {
130 options *CloseWaitClientOptions
131 }
132
133
134 func NewCloseWaitClient() common.Runner {
135 return &closeWaitClient{}
136 }
137
138
139 func (client *closeWaitClient) NewOptions() interface{} {
140 return &CloseWaitClientOptions{}
141 }
142
143
144 func (client *closeWaitClient) Run(logger *log.Logger, rawOptions interface{}) error {
145 if options, ok := rawOptions.(*CloseWaitClientOptions); ok {
146 client.options = options
147 } else {
148 return errors.New("invalid type")
149 }
150
151 logger.Printf("Run %v", client.options)
152
153 addr, err := net.ResolveTCPAddr("tcp", client.options.RemoteAddr)
154 if err != nil {
155 return err
156 }
157
158 conn, err := net.DialTCP("tcp", nil, addr)
159 if err != nil {
160 return err
161 }
162 if !client.options.LeakConnection {
163 defer conn.Close()
164 }
165
166 logger.Printf("Connected to server")
167
168 if client.options.TimeoutSeconds > 0 {
169 delay := time.Duration(client.options.TimeoutSeconds) * time.Second
170 conn.SetReadDeadline(time.Now().Add(delay))
171 }
172
173 buf := make([]byte, 1, 1)
174 size, err := conn.Read(buf)
175
176 if err != nil && err != io.EOF {
177 return err
178 }
179
180 if size != 0 {
181 return errors.New("Got data but expected EOF")
182 }
183
184 logger.Printf("Server has half-closed the connection, waiting %v seconds",
185 client.options.PostFinTimeoutSeconds)
186
187 if client.options.LeakConnection {
188 logger.Printf("Leaking client connection (assigning to global variable)")
189 leakedConnection = conn
190 }
191
192 <-time.After(
193 time.Duration(client.options.PostFinTimeoutSeconds) * time.Second)
194
195 logger.Printf("Done")
196
197 return nil
198 }
199
View as plain text