blob: 024505e7c628a6cf15ca2ecaeecba1625173676c [file] [log] [blame]
Russ Coxa0bcaf42009-06-25 20:24:55 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package net
6
7import (
Brad Fitzpatrick7a7ea012016-10-15 16:56:51 +01008 "errors"
9 "fmt"
Russ Coxeb692922011-11-01 22:05:34 -040010 "io"
Mikio Hara92b74d02016-02-19 17:45:22 +090011 "net/internal/socktest"
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020012 "os"
Fazlul Shahriar58423362011-10-31 11:47:44 -040013 "runtime"
Robert Griesemera3d10452009-12-15 15:35:38 -080014 "testing"
Mikio Hara2e086942016-01-28 11:05:03 +090015 "time"
Russ Coxa0bcaf42009-06-25 20:24:55 -070016)
17
Mikio Hara4f38ef82015-04-29 17:16:21 +090018func TestCloseRead(t *testing.T) {
19 switch runtime.GOOS {
Brad Fitzpatrick1bcfca02016-10-15 15:52:57 +010020 case "plan9":
Mikio Hara4f38ef82015-04-29 17:16:21 +090021 t.Skipf("not supported on %s", runtime.GOOS)
Brad Fitzpatrick394842e2011-09-28 08:12:38 -070022 }
23
Mikio Hara4f38ef82015-04-29 17:16:21 +090024 for _, network := range []string{"tcp", "unix", "unixpacket"} {
25 if !testableNetwork(network) {
26 t.Logf("skipping %s test", network)
27 continue
28 }
29
30 ln, err := newLocalListener(network)
31 if err != nil {
32 t.Fatal(err)
33 }
34 switch network {
35 case "unix", "unixpacket":
36 defer os.Remove(ln.Addr().String())
37 }
Dave Cheneya00958a2013-06-21 11:13:14 +100038 defer ln.Close()
Mikio Hara4f38ef82015-04-29 17:16:21 +090039
40 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
Brad Fitzpatrick394842e2011-09-28 08:12:38 -070041 if err != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +090042 t.Fatal(err)
Brad Fitzpatrick394842e2011-09-28 08:12:38 -070043 }
Mikio Hara4f38ef82015-04-29 17:16:21 +090044 switch network {
45 case "unix", "unixpacket":
46 defer os.Remove(c.LocalAddr().String())
Mikio Haraec114442015-04-16 23:10:56 +090047 }
Mikio Hara4f38ef82015-04-29 17:16:21 +090048 defer c.Close()
Brad Fitzpatrick394842e2011-09-28 08:12:38 -070049
Mikio Hara4f38ef82015-04-29 17:16:21 +090050 switch c := c.(type) {
51 case *TCPConn:
52 err = c.CloseRead()
53 case *UnixConn:
54 err = c.CloseRead()
55 }
56 if err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -070057 if perr := parseCloseError(err, true); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +090058 t.Error(perr)
59 }
60 t.Fatal(err)
61 }
62 var b [1]byte
63 n, err := c.Read(b[:])
64 if n != 0 || err == nil {
65 t.Fatalf("got (%d, %v); want (0, error)", n, err)
66 }
Brad Fitzpatrick394842e2011-09-28 08:12:38 -070067 }
68}
Russ Cox5e4e3d82012-02-14 00:40:37 -050069
Mikio Hara4f38ef82015-04-29 17:16:21 +090070func TestCloseWrite(t *testing.T) {
71 switch runtime.GOOS {
72 case "nacl", "plan9":
73 t.Skipf("not supported on %s", runtime.GOOS)
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020074 }
Mikio Hara7b2b45e2015-03-26 23:26:45 +090075
Mikio Hara4f38ef82015-04-29 17:16:21 +090076 handler := func(ls *localServer, ln Listener) {
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020077 c, err := ln.Accept()
78 if err != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +090079 t.Error(err)
Mikio Haraf0433e42014-03-15 13:43:02 +090080 return
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020081 }
Mikio Hara4f38ef82015-04-29 17:16:21 +090082 defer c.Close()
83
84 var b [1]byte
85 n, err := c.Read(b[:])
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020086 if n != 0 || err != io.EOF {
Mikio Hara4f38ef82015-04-29 17:16:21 +090087 t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
Mikio Haraf0433e42014-03-15 13:43:02 +090088 return
Rémy Oudompheng0ce90452012-05-30 00:08:58 +020089 }
Mikio Hara4f38ef82015-04-29 17:16:21 +090090 switch c := c.(type) {
91 case *TCPConn:
92 err = c.CloseWrite()
93 case *UnixConn:
94 err = c.CloseWrite()
95 }
96 if err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -070097 if perr := parseCloseError(err, true); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +090098 t.Error(perr)
99 }
100 t.Error(err)
101 return
102 }
103 n, err = c.Write(b[:])
104 if err == nil {
105 t.Errorf("got (%d, %v); want (any, error)", n, err)
106 return
107 }
108 }
Rémy Oudompheng0ce90452012-05-30 00:08:58 +0200109
Mikio Hara4f38ef82015-04-29 17:16:21 +0900110 for _, network := range []string{"tcp", "unix", "unixpacket"} {
111 if !testableNetwork(network) {
112 t.Logf("skipping %s test", network)
113 continue
114 }
Rémy Oudompheng0ce90452012-05-30 00:08:58 +0200115
Mikio Hara4f38ef82015-04-29 17:16:21 +0900116 ls, err := newLocalServer(network)
117 if err != nil {
118 t.Fatal(err)
119 }
120 defer ls.teardown()
121 if err := ls.buildup(handler); err != nil {
122 t.Fatal(err)
123 }
124
125 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
126 if err != nil {
127 t.Fatal(err)
128 }
129 switch network {
130 case "unix", "unixpacket":
131 defer os.Remove(c.LocalAddr().String())
132 }
133 defer c.Close()
134
135 switch c := c.(type) {
136 case *TCPConn:
137 err = c.CloseWrite()
138 case *UnixConn:
139 err = c.CloseWrite()
140 }
141 if err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -0700142 if perr := parseCloseError(err, true); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +0900143 t.Error(perr)
144 }
145 t.Fatal(err)
146 }
147 var b [1]byte
148 n, err := c.Read(b[:])
149 if n != 0 || err != io.EOF {
150 t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err)
151 }
152 n, err = c.Write(b[:])
153 if err == nil {
154 t.Fatalf("got (%d, %v); want (any, error)", n, err)
155 }
Rémy Oudompheng0ce90452012-05-30 00:08:58 +0200156 }
157}
158
Mikio Hara4f38ef82015-04-29 17:16:21 +0900159func TestConnClose(t *testing.T) {
160 for _, network := range []string{"tcp", "unix", "unixpacket"} {
161 if !testableNetwork(network) {
162 t.Logf("skipping %s test", network)
163 continue
164 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500165
Mikio Hara4f38ef82015-04-29 17:16:21 +0900166 ln, err := newLocalListener(network)
167 if err != nil {
168 t.Fatal(err)
169 }
170 switch network {
171 case "unix", "unixpacket":
172 defer os.Remove(ln.Addr().String())
173 }
174 defer ln.Close()
175
176 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
177 if err != nil {
178 t.Fatal(err)
179 }
180 switch network {
181 case "unix", "unixpacket":
182 defer os.Remove(c.LocalAddr().String())
183 }
184 defer c.Close()
185
186 if err := c.Close(); err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -0700187 if perr := parseCloseError(err, false); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +0900188 t.Error(perr)
189 }
190 t.Fatal(err)
191 }
192 var b [1]byte
193 n, err := c.Read(b[:])
194 if n != 0 || err == nil {
195 t.Fatalf("got (%d, %v); want (0, error)", n, err)
196 }
197 }
198}
199
200func TestListenerClose(t *testing.T) {
201 for _, network := range []string{"tcp", "unix", "unixpacket"} {
202 if !testableNetwork(network) {
203 t.Logf("skipping %s test", network)
204 continue
205 }
206
207 ln, err := newLocalListener(network)
208 if err != nil {
209 t.Fatal(err)
210 }
211 switch network {
212 case "unix", "unixpacket":
213 defer os.Remove(ln.Addr().String())
214 }
Mikio Hara4f38ef82015-04-29 17:16:21 +0900215
Mikio Hara2e086942016-01-28 11:05:03 +0900216 dst := ln.Addr().String()
Mikio Hara4f38ef82015-04-29 17:16:21 +0900217 if err := ln.Close(); err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -0700218 if perr := parseCloseError(err, false); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +0900219 t.Error(perr)
220 }
221 t.Fatal(err)
222 }
Mikio Haraba57c882012-05-19 10:42:54 +0900223 c, err := ln.Accept()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500224 if err == nil {
Mikio Haraba57c882012-05-19 10:42:54 +0900225 c.Close()
Mikio Hara4f38ef82015-04-29 17:16:21 +0900226 t.Fatal("should fail")
Russ Cox5e4e3d82012-02-14 00:40:37 -0500227 }
Brad Fitzpatrick19aa42092015-10-16 04:41:34 +0000228
229 if network == "tcp" {
Mikio Hara2e086942016-01-28 11:05:03 +0900230 // We will have two TCP FSMs inside the
231 // kernel here. There's no guarantee that a
232 // signal comes from the far end FSM will be
233 // delivered immediately to the near end FSM,
234 // especially on the platforms that allow
235 // multiple consumer threads to pull pending
236 // established connections at the same time by
237 // enabling SO_REUSEPORT option such as Linux,
238 // DragonFly BSD. So we need to give some time
239 // quantum to the kernel.
240 //
241 // Note that net.inet.tcp.reuseport_ext=1 by
242 // default on DragonFly BSD.
243 time.Sleep(time.Millisecond)
244
245 cc, err := Dial("tcp", dst)
Brad Fitzpatrick19aa42092015-10-16 04:41:34 +0000246 if err == nil {
Mikio Hara2e086942016-01-28 11:05:03 +0900247 t.Error("Dial to closed TCP listener succeeded.")
Brad Fitzpatrick19aa42092015-10-16 04:41:34 +0000248 cc.Close()
249 }
250 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500251 }
252}
253
Mikio Hara4f38ef82015-04-29 17:16:21 +0900254func TestPacketConnClose(t *testing.T) {
255 for _, network := range []string{"udp", "unixgram"} {
256 if !testableNetwork(network) {
257 t.Logf("skipping %s test", network)
258 continue
Mikio Haraec114442015-04-16 23:10:56 +0900259 }
Alex Brainmanfa3e4fc2012-10-31 10:24:37 +1100260
Mikio Hara4f38ef82015-04-29 17:16:21 +0900261 c, err := newLocalPacketListener(network)
Alex Brainmanfa3e4fc2012-10-31 10:24:37 +1100262 if err != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +0900263 t.Fatal(err)
Alex Brainmanfa3e4fc2012-10-31 10:24:37 +1100264 }
Mikio Hara4f38ef82015-04-29 17:16:21 +0900265 switch network {
266 case "unixgram":
267 defer os.Remove(c.LocalAddr().String())
268 }
269 defer c.Close()
Alex Brainmanfa3e4fc2012-10-31 10:24:37 +1100270
Mikio Hara4f38ef82015-04-29 17:16:21 +0900271 if err := c.Close(); err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -0700272 if perr := parseCloseError(err, false); perr != nil {
Mikio Hara4f38ef82015-04-29 17:16:21 +0900273 t.Error(perr)
274 }
275 t.Fatal(err)
276 }
277 var b [1]byte
278 n, _, err := c.ReadFrom(b[:])
279 if n != 0 || err == nil {
280 t.Fatalf("got (%d, %v); want (0, error)", n, err)
281 }
Alex Brainmanfa3e4fc2012-10-31 10:24:37 +1100282 }
283}
Brad Fitzpatrick8ee90fa2015-11-04 02:17:57 -0500284
285// nacl was previous failing to reuse an address.
286func TestListenCloseListen(t *testing.T) {
287 const maxTries = 10
288 for tries := 0; tries < maxTries; tries++ {
289 ln, err := newLocalListener("tcp")
290 if err != nil {
291 t.Fatal(err)
292 }
293 addr := ln.Addr().String()
294 if err := ln.Close(); err != nil {
Ian Lance Taylorfb4b4342017-04-07 15:53:19 -0700295 if perr := parseCloseError(err, false); perr != nil {
Mikio Hara2e086942016-01-28 11:05:03 +0900296 t.Error(perr)
297 }
Brad Fitzpatrick8ee90fa2015-11-04 02:17:57 -0500298 t.Fatal(err)
299 }
300 ln, err = Listen("tcp", addr)
301 if err == nil {
302 // Success. nacl couldn't do this before.
303 ln.Close()
304 return
305 }
306 t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err)
307 }
Ian Lance Taylor9ceb1ac2015-11-18 11:10:59 -0800308 t.Fatalf("failed to listen/close/listen on same address after %d tries", maxTries)
Brad Fitzpatrick8ee90fa2015-11-04 02:17:57 -0500309}
Mikio Hara92b74d02016-02-19 17:45:22 +0900310
311// See golang.org/issue/6163, golang.org/issue/6987.
312func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
313 switch runtime.GOOS {
314 case "plan9":
315 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
316 }
317
318 syserr := make(chan error)
319 go func() {
320 defer close(syserr)
321 for _, err := range abortedConnRequestErrors {
322 syserr <- err
323 }
324 }()
325 sw.Set(socktest.FilterAccept, func(so *socktest.Status) (socktest.AfterFilter, error) {
326 if err, ok := <-syserr; ok {
327 return nil, err
328 }
329 return nil, nil
330 })
331 defer sw.Set(socktest.FilterAccept, nil)
332
333 operr := make(chan error, 1)
334 handler := func(ls *localServer, ln Listener) {
335 defer close(operr)
336 c, err := ln.Accept()
337 if err != nil {
338 if perr := parseAcceptError(err); perr != nil {
339 operr <- perr
340 }
341 operr <- err
342 return
343 }
344 c.Close()
345 }
346 ls, err := newLocalServer("tcp")
347 if err != nil {
348 t.Fatal(err)
349 }
350 defer ls.teardown()
351 if err := ls.buildup(handler); err != nil {
352 t.Fatal(err)
353 }
354
355 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
356 if err != nil {
357 t.Fatal(err)
358 }
359 c.Close()
360
361 for err := range operr {
362 t.Error(err)
363 }
364}
Brad Fitzpatrick5bcdd632016-05-18 21:54:12 +0000365
366func TestZeroByteRead(t *testing.T) {
367 for _, network := range []string{"tcp", "unix", "unixpacket"} {
368 if !testableNetwork(network) {
369 t.Logf("skipping %s test", network)
370 continue
371 }
372
373 ln, err := newLocalListener(network)
374 if err != nil {
375 t.Fatal(err)
376 }
377 connc := make(chan Conn, 1)
378 go func() {
379 defer ln.Close()
380 c, err := ln.Accept()
381 if err != nil {
382 t.Error(err)
383 }
384 connc <- c // might be nil
385 }()
386 c, err := Dial(network, ln.Addr().String())
387 if err != nil {
388 t.Fatal(err)
389 }
390 defer c.Close()
391 sc := <-connc
392 if sc == nil {
393 continue
394 }
395 defer sc.Close()
396
397 if runtime.GOOS == "windows" {
398 // A zero byte read on Windows caused a wait for readability first.
399 // Rather than change that behavior, satisfy it in this test.
400 // See Issue 15735.
401 go io.WriteString(sc, "a")
402 }
403
404 n, err := c.Read(nil)
405 if n != 0 || err != nil {
406 t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
407 }
408
409 if runtime.GOOS == "windows" {
410 // Same as comment above.
411 go io.WriteString(c, "a")
412 }
413 n, err = sc.Read(nil)
414 if n != 0 || err != nil {
415 t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
416 }
417 }
418}
Brad Fitzpatrick8e69d432016-09-27 20:50:57 +0000419
420// withTCPConnPair sets up a TCP connection between two peers, then
421// runs peer1 and peer2 concurrently. withTCPConnPair returns when
422// both have completed.
423func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) {
424 ln, err := newLocalListener("tcp")
425 if err != nil {
426 t.Fatal(err)
427 }
428 defer ln.Close()
429 errc := make(chan error, 2)
430 go func() {
431 c1, err := ln.Accept()
432 if err != nil {
433 errc <- err
434 return
435 }
436 defer c1.Close()
437 errc <- peer1(c1.(*TCPConn))
438 }()
439 go func() {
440 c2, err := Dial("tcp", ln.Addr().String())
441 if err != nil {
442 errc <- err
443 return
444 }
445 defer c2.Close()
446 errc <- peer2(c2.(*TCPConn))
447 }()
448 for i := 0; i < 2; i++ {
449 if err := <-errc; err != nil {
450 t.Fatal(err)
451 }
452 }
453}
Brad Fitzpatrick7a7ea012016-10-15 16:56:51 +0100454
455// Tests that a blocked Read is interrupted by a concurrent SetReadDeadline
456// modifying that Conn's read deadline to the past.
457// See golang.org/cl/30164 which documented this. The net/http package
458// depends on this.
459func TestReadTimeoutUnblocksRead(t *testing.T) {
460 serverDone := make(chan struct{})
461 server := func(cs *TCPConn) error {
462 defer close(serverDone)
463 errc := make(chan error, 1)
464 go func() {
465 defer close(errc)
466 go func() {
467 // TODO: find a better way to wait
468 // until we're blocked in the cs.Read
469 // call below. Sleep is lame.
470 time.Sleep(100 * time.Millisecond)
471
472 // Interrupt the upcoming Read, unblocking it:
473 cs.SetReadDeadline(time.Unix(123, 0)) // time in the past
474 }()
475 var buf [1]byte
476 n, err := cs.Read(buf[:1])
477 if n != 0 || err == nil {
478 errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err)
479 }
480 }()
481 select {
482 case err := <-errc:
483 return err
484 case <-time.After(5 * time.Second):
485 buf := make([]byte, 2<<20)
486 buf = buf[:runtime.Stack(buf, true)]
487 println("Stacks at timeout:\n", string(buf))
488 return errors.New("timeout waiting for Read to finish")
489 }
490
491 }
492 // Do nothing in the client. Never write. Just wait for the
493 // server's half to be done.
494 client := func(*TCPConn) error {
495 <-serverDone
496 return nil
497 }
498 withTCPConnPair(t, client, server)
499}
Brad Fitzpatrick9be14c42016-11-15 03:31:47 +0000500
501// Issue 17695: verify that a blocked Read is woken up by a Close.
502func TestCloseUnblocksRead(t *testing.T) {
503 t.Parallel()
504 server := func(cs *TCPConn) error {
505 // Give the client time to get stuck in a Read:
506 time.Sleep(20 * time.Millisecond)
507 cs.Close()
508 return nil
509 }
510 client := func(ss *TCPConn) error {
511 n, err := ss.Read([]byte{0})
512 if n != 0 || err != io.EOF {
513 return fmt.Errorf("Read = %v, %v; want 0, EOF", n, err)
514 }
515 return nil
516 }
517 withTCPConnPair(t, client, server)
518}