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