blob: dd6f4df3b9c0978772557b664b2c65a8b1903422 [file] [log] [blame]
Mikio Hara89b26762013-09-11 10:48:53 -04001// Copyright 2013 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
Mikio Haraf0775052015-04-02 23:11:39 +09007import (
Mikio Hara9b184fd2015-05-01 07:49:12 +09008 "errors"
Mikio Haraf0775052015-04-02 23:11:39 +09009 "fmt"
Mikio Hara832c5732015-04-19 23:42:11 +090010 "io/ioutil"
Mikio Haraf0775052015-04-02 23:11:39 +090011 "os"
12 "sync"
Mikio Hara98e05562015-04-28 21:17:46 +090013 "testing"
Mikio Hara832c5732015-04-19 23:42:11 +090014 "time"
Mikio Haraf0775052015-04-02 23:11:39 +090015)
16
Mikio Hara832c5732015-04-19 23:42:11 +090017// testUnixAddr uses ioutil.TempFile to get a name that is unique.
18// It also uses /tmp directory in case it is prohibited to create UNIX
19// sockets in TMPDIR.
20func testUnixAddr() string {
Mikio Hara76d67ea2015-05-06 10:41:01 +090021 f, err := ioutil.TempFile("", "go-nettest")
Mikio Hara832c5732015-04-19 23:42:11 +090022 if err != nil {
23 panic(err)
24 }
25 addr := f.Name()
26 f.Close()
27 os.Remove(addr)
28 return addr
29}
30
Mikio Haraf0775052015-04-02 23:11:39 +090031func newLocalListener(network string) (Listener, error) {
32 switch network {
33 case "tcp", "tcp4", "tcp6":
34 if supportsIPv4 {
35 return Listen("tcp4", "127.0.0.1:0")
36 }
37 if supportsIPv6 {
38 return Listen("tcp6", "[::1]:0")
39 }
40 case "unix", "unixpacket":
41 return Listen(network, testUnixAddr())
42 }
43 return nil, fmt.Errorf("%s is not supported", network)
44}
45
Mikio Hara9b184fd2015-05-01 07:49:12 +090046func newDualStackListener() (lns []*TCPListener, err error) {
47 var args = []struct {
48 network string
49 TCPAddr
50 }{
51 {"tcp4", TCPAddr{IP: IPv4(127, 0, 0, 1)}},
52 {"tcp6", TCPAddr{IP: IPv6loopback}},
53 }
54 for i := 0; i < 64; i++ {
55 var port int
56 var lns []*TCPListener
57 for _, arg := range args {
58 arg.TCPAddr.Port = port
59 ln, err := ListenTCP(arg.network, &arg.TCPAddr)
60 if err != nil {
61 continue
62 }
63 port = ln.Addr().(*TCPAddr).Port
64 lns = append(lns, ln)
65 }
66 if len(lns) != len(args) {
67 for _, ln := range lns {
68 ln.Close()
69 }
70 continue
71 }
72 return lns, nil
73 }
74 return nil, errors.New("no dualstack port available")
75}
76
Mikio Haraf0775052015-04-02 23:11:39 +090077type localServer struct {
78 lnmu sync.RWMutex
79 Listener
80 done chan bool // signal that indicates server stopped
81}
82
83func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
84 go func() {
85 handler(ls, ls.Listener)
86 close(ls.done)
87 }()
88 return nil
89}
90
91func (ls *localServer) teardown() error {
92 ls.lnmu.Lock()
93 if ls.Listener != nil {
94 network := ls.Listener.Addr().Network()
95 address := ls.Listener.Addr().String()
96 ls.Listener.Close()
97 <-ls.done
98 ls.Listener = nil
99 switch network {
100 case "unix", "unixpacket":
101 os.Remove(address)
102 }
103 }
104 ls.lnmu.Unlock()
105 return nil
106}
107
108func newLocalServer(network string) (*localServer, error) {
109 ln, err := newLocalListener(network)
110 if err != nil {
111 return nil, err
112 }
113 return &localServer{Listener: ln, done: make(chan bool)}, nil
114}
Mikio Hara89b26762013-09-11 10:48:53 -0400115
116type streamListener struct {
Mikio Haraf0775052015-04-02 23:11:39 +0900117 network, address string
118 Listener
119 done chan bool // signal that indicates server stopped
120}
121
122func (sl *streamListener) newLocalServer() (*localServer, error) {
123 return &localServer{Listener: sl.Listener, done: make(chan bool)}, nil
Mikio Hara89b26762013-09-11 10:48:53 -0400124}
125
126type dualStackServer struct {
127 lnmu sync.RWMutex
128 lns []streamListener
129 port string
130
131 cmu sync.RWMutex
132 cs []Conn // established connections at the passive open side
133}
134
Mikio Haraf0775052015-04-02 23:11:39 +0900135func (dss *dualStackServer) buildup(handler func(*dualStackServer, Listener)) error {
Mikio Hara89b26762013-09-11 10:48:53 -0400136 for i := range dss.lns {
Mikio Haraf0775052015-04-02 23:11:39 +0900137 go func(i int) {
138 handler(dss, dss.lns[i].Listener)
139 close(dss.lns[i].done)
140 }(i)
Mikio Hara89b26762013-09-11 10:48:53 -0400141 }
142 return nil
143}
144
145func (dss *dualStackServer) putConn(c Conn) error {
146 dss.cmu.Lock()
147 dss.cs = append(dss.cs, c)
148 dss.cmu.Unlock()
149 return nil
150}
151
Mikio Haraf0775052015-04-02 23:11:39 +0900152func (dss *dualStackServer) teardownNetwork(network string) error {
Mikio Hara89b26762013-09-11 10:48:53 -0400153 dss.lnmu.Lock()
154 for i := range dss.lns {
Mikio Haraf0775052015-04-02 23:11:39 +0900155 if network == dss.lns[i].network && dss.lns[i].Listener != nil {
156 dss.lns[i].Listener.Close()
157 <-dss.lns[i].done
158 dss.lns[i].Listener = nil
Mikio Hara89b26762013-09-11 10:48:53 -0400159 }
160 }
161 dss.lnmu.Unlock()
162 return nil
163}
164
165func (dss *dualStackServer) teardown() error {
166 dss.lnmu.Lock()
167 for i := range dss.lns {
Mikio Haraf0775052015-04-02 23:11:39 +0900168 if dss.lns[i].Listener != nil {
169 dss.lns[i].Listener.Close()
170 <-dss.lns[i].done
Mikio Hara89b26762013-09-11 10:48:53 -0400171 }
172 }
Mikio Haraf0775052015-04-02 23:11:39 +0900173 dss.lns = dss.lns[:0]
Mikio Hara89b26762013-09-11 10:48:53 -0400174 dss.lnmu.Unlock()
175 dss.cmu.Lock()
176 for _, c := range dss.cs {
177 c.Close()
178 }
Mikio Haraf0775052015-04-02 23:11:39 +0900179 dss.cs = dss.cs[:0]
Mikio Hara89b26762013-09-11 10:48:53 -0400180 dss.cmu.Unlock()
181 return nil
182}
183
184func newDualStackServer(lns []streamListener) (*dualStackServer, error) {
185 dss := &dualStackServer{lns: lns, port: "0"}
186 for i := range dss.lns {
Mikio Haraf0775052015-04-02 23:11:39 +0900187 ln, err := Listen(dss.lns[i].network, JoinHostPort(dss.lns[i].address, dss.port))
Mikio Hara89b26762013-09-11 10:48:53 -0400188 if err != nil {
Dave Cheney994b2d42015-05-22 12:55:47 +1000189 for _, ln := range dss.lns[:i] {
Mikio Haraf0775052015-04-02 23:11:39 +0900190 ln.Listener.Close()
191 }
Mikio Hara89b26762013-09-11 10:48:53 -0400192 return nil, err
193 }
Mikio Haraf0775052015-04-02 23:11:39 +0900194 dss.lns[i].Listener = ln
195 dss.lns[i].done = make(chan bool)
Mikio Hara89b26762013-09-11 10:48:53 -0400196 if dss.port == "0" {
197 if _, dss.port, err = SplitHostPort(ln.Addr().String()); err != nil {
Mikio Haraf0775052015-04-02 23:11:39 +0900198 for _, ln := range dss.lns {
199 ln.Listener.Close()
200 }
Mikio Hara89b26762013-09-11 10:48:53 -0400201 return nil, err
202 }
203 }
204 }
205 return dss, nil
206}
Mikio Hara832c5732015-04-19 23:42:11 +0900207
208func transponder(ln Listener, ch chan<- error) {
209 defer close(ch)
210
211 switch ln := ln.(type) {
212 case *TCPListener:
213 ln.SetDeadline(time.Now().Add(someTimeout))
214 case *UnixListener:
215 ln.SetDeadline(time.Now().Add(someTimeout))
216 }
217 c, err := ln.Accept()
218 if err != nil {
219 if perr := parseAcceptError(err); perr != nil {
220 ch <- perr
221 }
222 ch <- err
223 return
224 }
225 defer c.Close()
226
227 network := ln.Addr().Network()
228 if c.LocalAddr().Network() != network || c.LocalAddr().Network() != network {
229 ch <- fmt.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
230 return
231 }
232 c.SetDeadline(time.Now().Add(someTimeout))
233 c.SetReadDeadline(time.Now().Add(someTimeout))
234 c.SetWriteDeadline(time.Now().Add(someTimeout))
235
236 b := make([]byte, 256)
237 n, err := c.Read(b)
238 if err != nil {
239 if perr := parseReadError(err); perr != nil {
240 ch <- perr
241 }
242 ch <- err
243 return
244 }
245 if _, err := c.Write(b[:n]); err != nil {
246 if perr := parseWriteError(err); perr != nil {
247 ch <- perr
248 }
249 ch <- err
250 return
251 }
252}
253
254func transceiver(c Conn, wb []byte, ch chan<- error) {
255 defer close(ch)
256
257 c.SetDeadline(time.Now().Add(someTimeout))
258 c.SetReadDeadline(time.Now().Add(someTimeout))
259 c.SetWriteDeadline(time.Now().Add(someTimeout))
260
261 n, err := c.Write(wb)
262 if err != nil {
263 if perr := parseWriteError(err); perr != nil {
264 ch <- perr
265 }
266 ch <- err
267 return
268 }
269 if n != len(wb) {
270 ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
271 }
272 rb := make([]byte, len(wb))
273 n, err = c.Read(rb)
274 if err != nil {
275 if perr := parseReadError(err); perr != nil {
276 ch <- perr
277 }
278 ch <- err
279 return
280 }
281 if n != len(wb) {
282 ch <- fmt.Errorf("read %d; want %d", n, len(wb))
283 }
284}
285
Mikio Hara98e05562015-04-28 21:17:46 +0900286func timeoutReceiver(c Conn, d, min, max time.Duration, ch chan<- error) {
287 var err error
288 defer func() { ch <- err }()
289
290 t0 := time.Now()
291 if err = c.SetReadDeadline(time.Now().Add(d)); err != nil {
292 return
293 }
294 b := make([]byte, 256)
295 var n int
296 n, err = c.Read(b)
297 t1 := time.Now()
298 if n != 0 || err == nil || !err.(Error).Timeout() {
299 err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
300 return
301 }
302 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
303 err = fmt.Errorf("Read took %s; expected %s", dt, d)
304 return
305 }
306}
307
308func timeoutTransmitter(c Conn, d, min, max time.Duration, ch chan<- error) {
309 var err error
310 defer func() { ch <- err }()
311
312 t0 := time.Now()
313 if err = c.SetWriteDeadline(time.Now().Add(d)); err != nil {
314 return
315 }
316 var n int
317 for {
318 n, err = c.Write([]byte("TIMEOUT TRANSMITTER"))
319 if err != nil {
320 break
321 }
322 }
323 t1 := time.Now()
324 if err == nil || !err.(Error).Timeout() {
325 err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err)
326 return
327 }
328 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
329 err = fmt.Errorf("Write took %s; expected %s", dt, d)
330 return
331 }
332}
333
Mikio Hara832c5732015-04-19 23:42:11 +0900334func newLocalPacketListener(network string) (PacketConn, error) {
335 switch network {
336 case "udp", "udp4", "udp6":
337 if supportsIPv4 {
338 return ListenPacket("udp4", "127.0.0.1:0")
339 }
340 if supportsIPv6 {
341 return ListenPacket("udp6", "[::1]:0")
342 }
343 case "unixgram":
344 return ListenPacket(network, testUnixAddr())
345 }
346 return nil, fmt.Errorf("%s is not supported", network)
347}
348
Mikio Hara9b184fd2015-05-01 07:49:12 +0900349func newDualStackPacketListener() (cs []*UDPConn, err error) {
350 var args = []struct {
351 network string
352 UDPAddr
353 }{
354 {"udp4", UDPAddr{IP: IPv4(127, 0, 0, 1)}},
355 {"udp6", UDPAddr{IP: IPv6loopback}},
356 }
357 for i := 0; i < 64; i++ {
358 var port int
359 var cs []*UDPConn
360 for _, arg := range args {
361 arg.UDPAddr.Port = port
362 c, err := ListenUDP(arg.network, &arg.UDPAddr)
363 if err != nil {
364 continue
365 }
366 port = c.LocalAddr().(*UDPAddr).Port
367 cs = append(cs, c)
368 }
369 if len(cs) != len(args) {
370 for _, c := range cs {
371 c.Close()
372 }
373 continue
374 }
375 return cs, nil
376 }
377 return nil, errors.New("no dualstack port available")
378}
379
Mikio Hara832c5732015-04-19 23:42:11 +0900380type localPacketServer struct {
381 pcmu sync.RWMutex
382 PacketConn
383 done chan bool // signal that indicates server stopped
384}
385
386func (ls *localPacketServer) buildup(handler func(*localPacketServer, PacketConn)) error {
387 go func() {
388 handler(ls, ls.PacketConn)
389 close(ls.done)
390 }()
391 return nil
392}
393
394func (ls *localPacketServer) teardown() error {
395 ls.pcmu.Lock()
396 if ls.PacketConn != nil {
397 network := ls.PacketConn.LocalAddr().Network()
398 address := ls.PacketConn.LocalAddr().String()
399 ls.PacketConn.Close()
400 <-ls.done
401 ls.PacketConn = nil
402 switch network {
403 case "unixgram":
404 os.Remove(address)
405 }
406 }
407 ls.pcmu.Unlock()
408 return nil
409}
410
411func newLocalPacketServer(network string) (*localPacketServer, error) {
412 c, err := newLocalPacketListener(network)
413 if err != nil {
414 return nil, err
415 }
416 return &localPacketServer{PacketConn: c, done: make(chan bool)}, nil
417}
418
419type packetListener struct {
420 PacketConn
421}
422
423func (pl *packetListener) newLocalServer() (*localPacketServer, error) {
424 return &localPacketServer{PacketConn: pl.PacketConn, done: make(chan bool)}, nil
425}
426
427func packetTransponder(c PacketConn, ch chan<- error) {
428 defer close(ch)
429
430 c.SetDeadline(time.Now().Add(someTimeout))
431 c.SetReadDeadline(time.Now().Add(someTimeout))
432 c.SetWriteDeadline(time.Now().Add(someTimeout))
433
434 b := make([]byte, 256)
435 n, peer, err := c.ReadFrom(b)
436 if err != nil {
437 if perr := parseReadError(err); perr != nil {
438 ch <- perr
439 }
440 ch <- err
441 return
442 }
443 if peer == nil { // for connected-mode sockets
444 switch c.LocalAddr().Network() {
445 case "udp":
446 peer, err = ResolveUDPAddr("udp", string(b[:n]))
447 case "unixgram":
448 peer, err = ResolveUnixAddr("unixgram", string(b[:n]))
449 }
450 if err != nil {
451 ch <- err
452 return
453 }
454 }
455 if _, err := c.WriteTo(b[:n], peer); err != nil {
456 if perr := parseWriteError(err); perr != nil {
457 ch <- perr
458 }
459 ch <- err
460 return
461 }
462}
463
464func packetTransceiver(c PacketConn, wb []byte, dst Addr, ch chan<- error) {
465 defer close(ch)
466
467 c.SetDeadline(time.Now().Add(someTimeout))
468 c.SetReadDeadline(time.Now().Add(someTimeout))
469 c.SetWriteDeadline(time.Now().Add(someTimeout))
470
471 n, err := c.WriteTo(wb, dst)
472 if err != nil {
473 if perr := parseWriteError(err); perr != nil {
474 ch <- perr
475 }
476 ch <- err
477 return
478 }
479 if n != len(wb) {
480 ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
481 }
482 rb := make([]byte, len(wb))
483 n, _, err = c.ReadFrom(rb)
484 if err != nil {
485 if perr := parseReadError(err); perr != nil {
486 ch <- perr
487 }
488 ch <- err
489 return
490 }
491 if n != len(wb) {
492 ch <- fmt.Errorf("read %d; want %d", n, len(wb))
493 }
494}
Mikio Hara98e05562015-04-28 21:17:46 +0900495
496func timeoutPacketReceiver(c PacketConn, d, min, max time.Duration, ch chan<- error) {
497 var err error
498 defer func() { ch <- err }()
499
500 t0 := time.Now()
501 if err = c.SetReadDeadline(time.Now().Add(d)); err != nil {
502 return
503 }
504 b := make([]byte, 256)
505 var n int
506 n, _, err = c.ReadFrom(b)
507 t1 := time.Now()
508 if n != 0 || err == nil || !err.(Error).Timeout() {
509 err = fmt.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n, err)
510 return
511 }
512 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
513 err = fmt.Errorf("ReadFrom took %s; expected %s", dt, d)
514 return
515 }
516}