1 // 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.
19 // testUnixAddr uses ioutil.TempFile to get a name that is unique.
20 // It also uses /tmp directory in case it is prohibited to create UNIX
22 func testUnixAddr() string {
23 f
, err
:= ioutil
.TempFile("", "go-nettest")
33 func newLocalListener(network
string) (Listener
, error
) {
37 if ln
, err
:= Listen("tcp4", "127.0.0.1:0"); err
== nil {
42 return Listen("tcp6", "[::1]:0")
46 return Listen("tcp4", "127.0.0.1:0")
50 return Listen("tcp6", "[::1]:0")
52 case "unix", "unixpacket":
53 return Listen(network
, testUnixAddr())
55 return nil, fmt
.Errorf("%s is not supported", network
)
58 func newDualStackListener() (lns
[]*TCPListener
, err error
) {
63 {"tcp4", TCPAddr
{IP
: IPv4(127, 0, 0, 1)}},
64 {"tcp6", TCPAddr
{IP
: IPv6loopback
}},
66 for i
:= 0; i
< 64; i
++ {
68 var lns
[]*TCPListener
69 for _
, arg
:= range args
{
70 arg
.TCPAddr
.Port
= port
71 ln
, err
:= ListenTCP(arg
.network
, &arg
.TCPAddr
)
75 port
= ln
.Addr().(*TCPAddr
).Port
78 if len(lns
) != len(args
) {
79 for _
, ln
:= range lns
{
86 return nil, errors
.New("no dualstack port available")
89 type localServer
struct {
92 done
chan bool // signal that indicates server stopped
95 func (ls
*localServer
) buildup(handler
func(*localServer
, Listener
)) error
{
97 handler(ls
, ls
.Listener
)
103 func (ls
*localServer
) teardown() error
{
105 if ls
.Listener
!= nil {
106 network
:= ls
.Listener
.Addr().Network()
107 address
:= ls
.Listener
.Addr().String()
112 case "unix", "unixpacket":
120 func newLocalServer(network
string) (*localServer
, error
) {
121 ln
, err
:= newLocalListener(network
)
125 return &localServer
{Listener
: ln
, done
: make(chan bool)}, nil
128 type streamListener
struct {
129 network
, address
string
131 done
chan bool // signal that indicates server stopped
134 func (sl
*streamListener
) newLocalServer() (*localServer
, error
) {
135 return &localServer
{Listener
: sl
.Listener
, done
: make(chan bool)}, nil
138 type dualStackServer
struct {
144 cs
[]Conn
// established connections at the passive open side
147 func (dss
*dualStackServer
) buildup(handler
func(*dualStackServer
, Listener
)) error
{
148 for i
:= range dss
.lns
{
150 handler(dss
, dss
.lns
[i
].Listener
)
151 close(dss
.lns
[i
].done
)
157 func (dss
*dualStackServer
) teardownNetwork(network
string) error
{
159 for i
:= range dss
.lns
{
160 if network
== dss
.lns
[i
].network
&& dss
.lns
[i
].Listener
!= nil {
161 dss
.lns
[i
].Listener
.Close()
163 dss
.lns
[i
].Listener
= nil
170 func (dss
*dualStackServer
) teardown() error
{
172 for i
:= range dss
.lns
{
173 if dss
.lns
[i
].Listener
!= nil {
174 dss
.lns
[i
].Listener
.Close()
178 dss
.lns
= dss
.lns
[:0]
181 for _
, c
:= range dss
.cs
{
189 func newDualStackServer() (*dualStackServer
, error
) {
190 lns
, err
:= newDualStackListener()
194 _
, port
, err
:= SplitHostPort(lns
[0].Addr().String())
200 return &dualStackServer
{
201 lns
: []streamListener
{
202 {network
: "tcp4", address
: lns
[0].Addr().String(), Listener
: lns
[0], done
: make(chan bool)},
203 {network
: "tcp6", address
: lns
[1].Addr().String(), Listener
: lns
[1], done
: make(chan bool)},
209 func transponder(ln Listener
, ch
chan<- error
) {
212 switch ln
:= ln
.(type) {
214 ln
.SetDeadline(time
.Now().Add(someTimeout
))
216 ln
.SetDeadline(time
.Now().Add(someTimeout
))
218 c
, err
:= ln
.Accept()
220 if perr
:= parseAcceptError(err
); perr
!= nil {
228 network
:= ln
.Addr().Network()
229 if c
.LocalAddr().Network() != network || c
.RemoteAddr().Network() != network
{
230 ch
<- fmt
.Errorf("got %v->%v; expected %v->%v", c
.LocalAddr().Network(), c
.RemoteAddr().Network(), network
, network
)
233 c
.SetDeadline(time
.Now().Add(someTimeout
))
234 c
.SetReadDeadline(time
.Now().Add(someTimeout
))
235 c
.SetWriteDeadline(time
.Now().Add(someTimeout
))
237 b
:= make([]byte, 256)
240 if perr
:= parseReadError(err
); perr
!= nil {
246 if _
, err
:= c
.Write(b
[:n
]); err
!= nil {
247 if perr
:= parseWriteError(err
); perr
!= nil {
255 func transceiver(c Conn
, wb
[]byte, ch
chan<- error
) {
258 c
.SetDeadline(time
.Now().Add(someTimeout
))
259 c
.SetReadDeadline(time
.Now().Add(someTimeout
))
260 c
.SetWriteDeadline(time
.Now().Add(someTimeout
))
262 n
, err
:= c
.Write(wb
)
264 if perr
:= parseWriteError(err
); perr
!= nil {
271 ch
<- fmt
.Errorf("wrote %d; want %d", n
, len(wb
))
273 rb
:= make([]byte, len(wb
))
276 if perr
:= parseReadError(err
); perr
!= nil {
283 ch
<- fmt
.Errorf("read %d; want %d", n
, len(wb
))
287 func timeoutReceiver(c Conn
, d
, min
, max time
.Duration
, ch
chan<- error
) {
289 defer func() { ch
<- err
}()
292 if err
= c
.SetReadDeadline(time
.Now().Add(d
)); err
!= nil {
295 b
:= make([]byte, 256)
299 if n
!= 0 || err
== nil ||
!err
.(Error
).Timeout() {
300 err
= fmt
.Errorf("Read did not return (0, timeout): (%d, %v)", n
, err
)
303 if dt
:= t1
.Sub(t0
); min
> dt || dt
> max
&& !testing
.Short() {
304 err
= fmt
.Errorf("Read took %s; expected %s", dt
, d
)
309 func timeoutTransmitter(c Conn
, d
, min
, max time
.Duration
, ch
chan<- error
) {
311 defer func() { ch
<- err
}()
314 if err
= c
.SetWriteDeadline(time
.Now().Add(d
)); err
!= nil {
319 n
, err
= c
.Write([]byte("TIMEOUT TRANSMITTER"))
325 if err
== nil ||
!err
.(Error
).Timeout() {
326 err
= fmt
.Errorf("Write did not return (any, timeout): (%d, %v)", n
, err
)
329 if dt
:= t1
.Sub(t0
); min
> dt || dt
> max
&& !testing
.Short() {
330 err
= fmt
.Errorf("Write took %s; expected %s", dt
, d
)
335 func newLocalPacketListener(network
string) (PacketConn
, error
) {
339 return ListenPacket("udp4", "127.0.0.1:0")
342 return ListenPacket("udp6", "[::1]:0")
346 return ListenPacket("udp4", "127.0.0.1:0")
350 return ListenPacket("udp6", "[::1]:0")
353 return ListenPacket(network
, testUnixAddr())
355 return nil, fmt
.Errorf("%s is not supported", network
)
358 func newDualStackPacketListener() (cs
[]*UDPConn
, err error
) {
359 var args
= []struct {
363 {"udp4", UDPAddr
{IP
: IPv4(127, 0, 0, 1)}},
364 {"udp6", UDPAddr
{IP
: IPv6loopback
}},
366 for i
:= 0; i
< 64; i
++ {
369 for _
, arg
:= range args
{
370 arg
.UDPAddr
.Port
= port
371 c
, err
:= ListenUDP(arg
.network
, &arg
.UDPAddr
)
375 port
= c
.LocalAddr().(*UDPAddr
).Port
378 if len(cs
) != len(args
) {
379 for _
, c
:= range cs
{
386 return nil, errors
.New("no dualstack port available")
389 type localPacketServer
struct {
392 done
chan bool // signal that indicates server stopped
395 func (ls
*localPacketServer
) buildup(handler
func(*localPacketServer
, PacketConn
)) error
{
397 handler(ls
, ls
.PacketConn
)
403 func (ls
*localPacketServer
) teardown() error
{
405 if ls
.PacketConn
!= nil {
406 network
:= ls
.PacketConn
.LocalAddr().Network()
407 address
:= ls
.PacketConn
.LocalAddr().String()
408 ls
.PacketConn
.Close()
420 func newLocalPacketServer(network
string) (*localPacketServer
, error
) {
421 c
, err
:= newLocalPacketListener(network
)
425 return &localPacketServer
{PacketConn
: c
, done
: make(chan bool)}, nil
428 type packetListener
struct {
432 func (pl
*packetListener
) newLocalServer() (*localPacketServer
, error
) {
433 return &localPacketServer
{PacketConn
: pl
.PacketConn
, done
: make(chan bool)}, nil
436 func packetTransponder(c PacketConn
, ch
chan<- error
) {
439 c
.SetDeadline(time
.Now().Add(someTimeout
))
440 c
.SetReadDeadline(time
.Now().Add(someTimeout
))
441 c
.SetWriteDeadline(time
.Now().Add(someTimeout
))
443 b
:= make([]byte, 256)
444 n
, peer
, err
:= c
.ReadFrom(b
)
446 if perr
:= parseReadError(err
); perr
!= nil {
452 if peer
== nil { // for connected-mode sockets
453 switch c
.LocalAddr().Network() {
455 peer
, err
= ResolveUDPAddr("udp", string(b
[:n
]))
457 peer
, err
= ResolveUnixAddr("unixgram", string(b
[:n
]))
464 if _
, err
:= c
.WriteTo(b
[:n
], peer
); err
!= nil {
465 if perr
:= parseWriteError(err
); perr
!= nil {
473 func packetTransceiver(c PacketConn
, wb
[]byte, dst Addr
, ch
chan<- error
) {
476 c
.SetDeadline(time
.Now().Add(someTimeout
))
477 c
.SetReadDeadline(time
.Now().Add(someTimeout
))
478 c
.SetWriteDeadline(time
.Now().Add(someTimeout
))
480 n
, err
:= c
.WriteTo(wb
, dst
)
482 if perr
:= parseWriteError(err
); perr
!= nil {
489 ch
<- fmt
.Errorf("wrote %d; want %d", n
, len(wb
))
491 rb
:= make([]byte, len(wb
))
492 n
, _
, err
= c
.ReadFrom(rb
)
494 if perr
:= parseReadError(err
); perr
!= nil {
501 ch
<- fmt
.Errorf("read %d; want %d", n
, len(wb
))
505 func timeoutPacketReceiver(c PacketConn
, d
, min
, max time
.Duration
, ch
chan<- error
) {
507 defer func() { ch
<- err
}()
510 if err
= c
.SetReadDeadline(time
.Now().Add(d
)); err
!= nil {
513 b
:= make([]byte, 256)
515 n
, _
, err
= c
.ReadFrom(b
)
517 if n
!= 0 || err
== nil ||
!err
.(Error
).Timeout() {
518 err
= fmt
.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n
, err
)
521 if dt
:= t1
.Sub(t0
); min
> dt || dt
> max
&& !testing
.Short() {
522 err
= fmt
.Errorf("ReadFrom took %s; expected %s", dt
, d
)