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 // +build !nacl,!plan9,!windows
      6 
      7 package net
      8 
      9 import (
     10 	"bytes"
     11 	"internal/testenv"
     12 	"io/ioutil"
     13 	"os"
     14 	"reflect"
     15 	"runtime"
     16 	"syscall"
     17 	"testing"
     18 	"time"
     19 )
     20 
     21 func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
     22 	if !testableNetwork("unixgram") {
     23 		t.Skip("unixgram test")
     24 	}
     25 	if runtime.GOOS == "openbsd" {
     26 		testenv.SkipFlaky(t, 15157)
     27 	}
     28 
     29 	addr := testUnixAddr()
     30 	la, err := ResolveUnixAddr("unixgram", addr)
     31 	if err != nil {
     32 		t.Fatal(err)
     33 	}
     34 	c, err := ListenUnixgram("unixgram", la)
     35 	if err != nil {
     36 		t.Fatal(err)
     37 	}
     38 	defer func() {
     39 		c.Close()
     40 		os.Remove(addr)
     41 	}()
     42 
     43 	off := make(chan bool)
     44 	data := [5]byte{1, 2, 3, 4, 5}
     45 	go func() {
     46 		defer func() { off <- true }()
     47 		s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
     48 		if err != nil {
     49 			t.Error(err)
     50 			return
     51 		}
     52 		defer syscall.Close(s)
     53 		rsa := &syscall.SockaddrUnix{Name: addr}
     54 		if err := syscall.Sendto(s, data[:], 0, rsa); err != nil {
     55 			t.Error(err)
     56 			return
     57 		}
     58 	}()
     59 
     60 	<-off
     61 	b := make([]byte, 64)
     62 	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
     63 	n, from, err := c.ReadFrom(b)
     64 	if err != nil {
     65 		t.Fatal(err)
     66 	}
     67 	if from != nil {
     68 		t.Fatalf("unexpected peer address: %v", from)
     69 	}
     70 	if !bytes.Equal(b[:n], data[:]) {
     71 		t.Fatalf("got %v; want %v", b[:n], data[:])
     72 	}
     73 }
     74 
     75 func TestUnixgramZeroBytePayload(t *testing.T) {
     76 	if !testableNetwork("unixgram") {
     77 		t.Skip("unixgram test")
     78 	}
     79 
     80 	c1, err := newLocalPacketListener("unixgram")
     81 	if err != nil {
     82 		t.Fatal(err)
     83 	}
     84 	defer os.Remove(c1.LocalAddr().String())
     85 	defer c1.Close()
     86 
     87 	c2, err := Dial("unixgram", c1.LocalAddr().String())
     88 	if err != nil {
     89 		t.Fatal(err)
     90 	}
     91 	defer os.Remove(c2.LocalAddr().String())
     92 	defer c2.Close()
     93 
     94 	for _, genericRead := range []bool{false, true} {
     95 		n, err := c2.Write(nil)
     96 		if err != nil {
     97 			t.Fatal(err)
     98 		}
     99 		if n != 0 {
    100 			t.Errorf("got %d; want 0", n)
    101 		}
    102 		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
    103 		var b [1]byte
    104 		var peer Addr
    105 		if genericRead {
    106 			_, err = c1.(Conn).Read(b[:])
    107 		} else {
    108 			_, peer, err = c1.ReadFrom(b[:])
    109 		}
    110 		switch err {
    111 		case nil: // ReadFrom succeeds
    112 			if peer != nil { // peer is connected-mode
    113 				t.Fatalf("unexpected peer address: %v", peer)
    114 			}
    115 		default: // Read may timeout, it depends on the platform
    116 			if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
    117 				t.Fatal(err)
    118 			}
    119 		}
    120 	}
    121 }
    122 
    123 func TestUnixgramZeroByteBuffer(t *testing.T) {
    124 	if !testableNetwork("unixgram") {
    125 		t.Skip("unixgram test")
    126 	}
    127 	// issue 4352: Recvfrom failed with "address family not
    128 	// supported by protocol family" if zero-length buffer provided
    129 
    130 	c1, err := newLocalPacketListener("unixgram")
    131 	if err != nil {
    132 		t.Fatal(err)
    133 	}
    134 	defer os.Remove(c1.LocalAddr().String())
    135 	defer c1.Close()
    136 
    137 	c2, err := Dial("unixgram", c1.LocalAddr().String())
    138 	if err != nil {
    139 		t.Fatal(err)
    140 	}
    141 	defer os.Remove(c2.LocalAddr().String())
    142 	defer c2.Close()
    143 
    144 	b := []byte("UNIXGRAM ZERO BYTE BUFFER TEST")
    145 	for _, genericRead := range []bool{false, true} {
    146 		n, err := c2.Write(b)
    147 		if err != nil {
    148 			t.Fatal(err)
    149 		}
    150 		if n != len(b) {
    151 			t.Errorf("got %d; want %d", n, len(b))
    152 		}
    153 		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
    154 		var peer Addr
    155 		if genericRead {
    156 			_, err = c1.(Conn).Read(nil)
    157 		} else {
    158 			_, peer, err = c1.ReadFrom(nil)
    159 		}
    160 		switch err {
    161 		case nil: // ReadFrom succeeds
    162 			if peer != nil { // peer is connected-mode
    163 				t.Fatalf("unexpected peer address: %v", peer)
    164 			}
    165 		default: // Read may timeout, it depends on the platform
    166 			if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
    167 				t.Fatal(err)
    168 			}
    169 		}
    170 	}
    171 }
    172 
    173 func TestUnixgramWrite(t *testing.T) {
    174 	if !testableNetwork("unixgram") {
    175 		t.Skip("unixgram test")
    176 	}
    177 
    178 	addr := testUnixAddr()
    179 	laddr, err := ResolveUnixAddr("unixgram", addr)
    180 	if err != nil {
    181 		t.Fatal(err)
    182 	}
    183 	c, err := ListenPacket("unixgram", addr)
    184 	if err != nil {
    185 		t.Fatal(err)
    186 	}
    187 	defer os.Remove(addr)
    188 	defer c.Close()
    189 
    190 	testUnixgramWriteConn(t, laddr)
    191 	testUnixgramWritePacketConn(t, laddr)
    192 }
    193 
    194 func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) {
    195 	c, err := Dial("unixgram", raddr.String())
    196 	if err != nil {
    197 		t.Fatal(err)
    198 	}
    199 	defer c.Close()
    200 
    201 	b := []byte("CONNECTED-MODE SOCKET")
    202 	if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err == nil {
    203 		t.Fatal("should fail")
    204 	} else if err.(*OpError).Err != ErrWriteToConnected {
    205 		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
    206 	}
    207 	if _, err = c.(*UnixConn).WriteTo(b, raddr); err == nil {
    208 		t.Fatal("should fail")
    209 	} else if err.(*OpError).Err != ErrWriteToConnected {
    210 		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
    211 	}
    212 	if _, _, err = c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err == nil {
    213 		t.Fatal("should fail")
    214 	} else if err.(*OpError).Err != ErrWriteToConnected {
    215 		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
    216 	}
    217 	if _, err := c.Write(b); err != nil {
    218 		t.Fatal(err)
    219 	}
    220 }
    221 
    222 func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) {
    223 	addr := testUnixAddr()
    224 	c, err := ListenPacket("unixgram", addr)
    225 	if err != nil {
    226 		t.Fatal(err)
    227 	}
    228 	defer os.Remove(addr)
    229 	defer c.Close()
    230 
    231 	b := []byte("UNCONNECTED-MODE SOCKET")
    232 	if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err != nil {
    233 		t.Fatal(err)
    234 	}
    235 	if _, err := c.WriteTo(b, raddr); err != nil {
    236 		t.Fatal(err)
    237 	}
    238 	if _, _, err := c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err != nil {
    239 		t.Fatal(err)
    240 	}
    241 	if _, err := c.(*UnixConn).Write(b); err == nil {
    242 		t.Fatal("should fail")
    243 	}
    244 }
    245 
    246 func TestUnixConnLocalAndRemoteNames(t *testing.T) {
    247 	if !testableNetwork("unix") {
    248 		t.Skip("unix test")
    249 	}
    250 
    251 	handler := func(ls *localServer, ln Listener) {}
    252 	for _, laddr := range []string{"", testUnixAddr()} {
    253 		laddr := laddr
    254 		taddr := testUnixAddr()
    255 		ta, err := ResolveUnixAddr("unix", taddr)
    256 		if err != nil {
    257 			t.Fatal(err)
    258 		}
    259 		ln, err := ListenUnix("unix", ta)
    260 		if err != nil {
    261 			t.Fatal(err)
    262 		}
    263 		ls, err := (&streamListener{Listener: ln}).newLocalServer()
    264 		if err != nil {
    265 			t.Fatal(err)
    266 		}
    267 		defer ls.teardown()
    268 		if err := ls.buildup(handler); err != nil {
    269 			t.Fatal(err)
    270 		}
    271 
    272 		la, err := ResolveUnixAddr("unix", laddr)
    273 		if err != nil {
    274 			t.Fatal(err)
    275 		}
    276 		c, err := DialUnix("unix", la, ta)
    277 		if err != nil {
    278 			t.Fatal(err)
    279 		}
    280 		defer func() {
    281 			c.Close()
    282 			if la != nil {
    283 				defer os.Remove(laddr)
    284 			}
    285 		}()
    286 		if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
    287 			t.Fatal(err)
    288 		}
    289 
    290 		switch runtime.GOOS {
    291 		case "android", "linux":
    292 			if laddr == "" {
    293 				laddr = "@" // autobind feature
    294 			}
    295 		}
    296 		var connAddrs = [3]struct{ got, want Addr }{
    297 			{ln.Addr(), ta},
    298 			{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
    299 			{c.RemoteAddr(), ta},
    300 		}
    301 		for _, ca := range connAddrs {
    302 			if !reflect.DeepEqual(ca.got, ca.want) {
    303 				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
    304 			}
    305 		}
    306 	}
    307 }
    308 
    309 func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
    310 	if !testableNetwork("unixgram") {
    311 		t.Skip("unixgram test")
    312 	}
    313 
    314 	for _, laddr := range []string{"", testUnixAddr()} {
    315 		laddr := laddr
    316 		taddr := testUnixAddr()
    317 		ta, err := ResolveUnixAddr("unixgram", taddr)
    318 		if err != nil {
    319 			t.Fatal(err)
    320 		}
    321 		c1, err := ListenUnixgram("unixgram", ta)
    322 		if err != nil {
    323 			t.Fatal(err)
    324 		}
    325 		defer func() {
    326 			c1.Close()
    327 			os.Remove(taddr)
    328 		}()
    329 
    330 		var la *UnixAddr
    331 		if laddr != "" {
    332 			if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
    333 				t.Fatal(err)
    334 			}
    335 		}
    336 		c2, err := DialUnix("unixgram", la, ta)
    337 		if err != nil {
    338 			t.Fatal(err)
    339 		}
    340 		defer func() {
    341 			c2.Close()
    342 			if la != nil {
    343 				defer os.Remove(laddr)
    344 			}
    345 		}()
    346 
    347 		switch runtime.GOOS {
    348 		case "android", "linux":
    349 			if laddr == "" {
    350 				laddr = "@" // autobind feature
    351 			}
    352 		}
    353 
    354 		var connAddrs = [4]struct{ got, want Addr }{
    355 			{c1.LocalAddr(), ta},
    356 			{c1.RemoteAddr(), nil},
    357 			{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
    358 			{c2.RemoteAddr(), ta},
    359 		}
    360 		for _, ca := range connAddrs {
    361 			if !reflect.DeepEqual(ca.got, ca.want) {
    362 				t.Fatalf("got %#v; want %#v", ca.got, ca.want)
    363 			}
    364 		}
    365 	}
    366 }
    367 
    368 func TestUnixUnlink(t *testing.T) {
    369 	if !testableNetwork("unix") {
    370 		t.Skip("unix test")
    371 	}
    372 	name := testUnixAddr()
    373 
    374 	listen := func(t *testing.T) *UnixListener {
    375 		l, err := Listen("unix", name)
    376 		if err != nil {
    377 			t.Fatal(err)
    378 		}
    379 		return l.(*UnixListener)
    380 	}
    381 	checkExists := func(t *testing.T, desc string) {
    382 		if _, err := os.Stat(name); err != nil {
    383 			t.Fatalf("unix socket does not exist %s: %v", desc, err)
    384 		}
    385 	}
    386 	checkNotExists := func(t *testing.T, desc string) {
    387 		if _, err := os.Stat(name); err == nil {
    388 			t.Fatalf("unix socket does exist %s: %v", desc, err)
    389 		}
    390 	}
    391 
    392 	// Listener should remove on close.
    393 	t.Run("Listen", func(t *testing.T) {
    394 		l := listen(t)
    395 		checkExists(t, "after Listen")
    396 		l.Close()
    397 		checkNotExists(t, "after Listener close")
    398 	})
    399 
    400 	// FileListener should not.
    401 	t.Run("FileListener", func(t *testing.T) {
    402 		l := listen(t)
    403 		f, _ := l.File()
    404 		l1, _ := FileListener(f)
    405 		checkExists(t, "after FileListener")
    406 		f.Close()
    407 		checkExists(t, "after File close")
    408 		l1.Close()
    409 		checkExists(t, "after FileListener close")
    410 		l.Close()
    411 		checkNotExists(t, "after Listener close")
    412 	})
    413 
    414 	// Only first call to l.Close should remove.
    415 	t.Run("SecondClose", func(t *testing.T) {
    416 		l := listen(t)
    417 		checkExists(t, "after Listen")
    418 		l.Close()
    419 		checkNotExists(t, "after Listener close")
    420 		if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil {
    421 			t.Fatalf("cannot recreate socket file: %v", err)
    422 		}
    423 		checkExists(t, "after writing temp file")
    424 		l.Close()
    425 		checkExists(t, "after second Listener close")
    426 		os.Remove(name)
    427 	})
    428 
    429 	// SetUnlinkOnClose should do what it says.
    430 
    431 	t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
    432 		l := listen(t)
    433 		checkExists(t, "after Listen")
    434 		l.SetUnlinkOnClose(true)
    435 		l.Close()
    436 		checkNotExists(t, "after Listener close")
    437 	})
    438 
    439 	t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
    440 		l := listen(t)
    441 		checkExists(t, "after Listen")
    442 		l.SetUnlinkOnClose(false)
    443 		l.Close()
    444 		checkExists(t, "after Listener close")
    445 		os.Remove(name)
    446 	})
    447 
    448 	t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
    449 		l := listen(t)
    450 		f, _ := l.File()
    451 		l1, _ := FileListener(f)
    452 		checkExists(t, "after FileListener")
    453 		l1.(*UnixListener).SetUnlinkOnClose(true)
    454 		f.Close()
    455 		checkExists(t, "after File close")
    456 		l1.Close()
    457 		checkNotExists(t, "after FileListener close")
    458 		l.Close()
    459 	})
    460 
    461 	t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
    462 		l := listen(t)
    463 		f, _ := l.File()
    464 		l1, _ := FileListener(f)
    465 		checkExists(t, "after FileListener")
    466 		l1.(*UnixListener).SetUnlinkOnClose(false)
    467 		f.Close()
    468 		checkExists(t, "after File close")
    469 		l1.Close()
    470 		checkExists(t, "after FileListener close")
    471 		l.Close()
    472 	})
    473 }
    474