...

Source file src/net/tcpsock.go

Documentation: net

		 1  // 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  
		 5  package net
		 6  
		 7  import (
		 8  	"context"
		 9  	"internal/itoa"
		10  	"io"
		11  	"os"
		12  	"syscall"
		13  	"time"
		14  )
		15  
		16  // BUG(mikio): On JS and Windows, the File method of TCPConn and
		17  // TCPListener is not implemented.
		18  
		19  // TCPAddr represents the address of a TCP end point.
		20  type TCPAddr struct {
		21  	IP	 IP
		22  	Port int
		23  	Zone string // IPv6 scoped addressing zone
		24  }
		25  
		26  // Network returns the address's network name, "tcp".
		27  func (a *TCPAddr) Network() string { return "tcp" }
		28  
		29  func (a *TCPAddr) String() string {
		30  	if a == nil {
		31  		return "<nil>"
		32  	}
		33  	ip := ipEmptyString(a.IP)
		34  	if a.Zone != "" {
		35  		return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port))
		36  	}
		37  	return JoinHostPort(ip, itoa.Itoa(a.Port))
		38  }
		39  
		40  func (a *TCPAddr) isWildcard() bool {
		41  	if a == nil || a.IP == nil {
		42  		return true
		43  	}
		44  	return a.IP.IsUnspecified()
		45  }
		46  
		47  func (a *TCPAddr) opAddr() Addr {
		48  	if a == nil {
		49  		return nil
		50  	}
		51  	return a
		52  }
		53  
		54  // ResolveTCPAddr returns an address of TCP end point.
		55  //
		56  // The network must be a TCP network name.
		57  //
		58  // If the host in the address parameter is not a literal IP address or
		59  // the port is not a literal port number, ResolveTCPAddr resolves the
		60  // address to an address of TCP end point.
		61  // Otherwise, it parses the address as a pair of literal IP address
		62  // and port number.
		63  // The address parameter can use a host name, but this is not
		64  // recommended, because it will return at most one of the host name's
		65  // IP addresses.
		66  //
		67  // See func Dial for a description of the network and address
		68  // parameters.
		69  func ResolveTCPAddr(network, address string) (*TCPAddr, error) {
		70  	switch network {
		71  	case "tcp", "tcp4", "tcp6":
		72  	case "": // a hint wildcard for Go 1.0 undocumented behavior
		73  		network = "tcp"
		74  	default:
		75  		return nil, UnknownNetworkError(network)
		76  	}
		77  	addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address)
		78  	if err != nil {
		79  		return nil, err
		80  	}
		81  	return addrs.forResolve(network, address).(*TCPAddr), nil
		82  }
		83  
		84  // TCPConn is an implementation of the Conn interface for TCP network
		85  // connections.
		86  type TCPConn struct {
		87  	conn
		88  }
		89  
		90  // SyscallConn returns a raw network connection.
		91  // This implements the syscall.Conn interface.
		92  func (c *TCPConn) SyscallConn() (syscall.RawConn, error) {
		93  	if !c.ok() {
		94  		return nil, syscall.EINVAL
		95  	}
		96  	return newRawConn(c.fd)
		97  }
		98  
		99  // ReadFrom implements the io.ReaderFrom ReadFrom method.
	 100  func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
	 101  	if !c.ok() {
	 102  		return 0, syscall.EINVAL
	 103  	}
	 104  	n, err := c.readFrom(r)
	 105  	if err != nil && err != io.EOF {
	 106  		err = &OpError{Op: "readfrom", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 107  	}
	 108  	return n, err
	 109  }
	 110  
	 111  // CloseRead shuts down the reading side of the TCP connection.
	 112  // Most callers should just use Close.
	 113  func (c *TCPConn) CloseRead() error {
	 114  	if !c.ok() {
	 115  		return syscall.EINVAL
	 116  	}
	 117  	if err := c.fd.closeRead(); err != nil {
	 118  		return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 119  	}
	 120  	return nil
	 121  }
	 122  
	 123  // CloseWrite shuts down the writing side of the TCP connection.
	 124  // Most callers should just use Close.
	 125  func (c *TCPConn) CloseWrite() error {
	 126  	if !c.ok() {
	 127  		return syscall.EINVAL
	 128  	}
	 129  	if err := c.fd.closeWrite(); err != nil {
	 130  		return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 131  	}
	 132  	return nil
	 133  }
	 134  
	 135  // SetLinger sets the behavior of Close on a connection which still
	 136  // has data waiting to be sent or to be acknowledged.
	 137  //
	 138  // If sec < 0 (the default), the operating system finishes sending the
	 139  // data in the background.
	 140  //
	 141  // If sec == 0, the operating system discards any unsent or
	 142  // unacknowledged data.
	 143  //
	 144  // If sec > 0, the data is sent in the background as with sec < 0. On
	 145  // some operating systems after sec seconds have elapsed any remaining
	 146  // unsent data may be discarded.
	 147  func (c *TCPConn) SetLinger(sec int) error {
	 148  	if !c.ok() {
	 149  		return syscall.EINVAL
	 150  	}
	 151  	if err := setLinger(c.fd, sec); err != nil {
	 152  		return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 153  	}
	 154  	return nil
	 155  }
	 156  
	 157  // SetKeepAlive sets whether the operating system should send
	 158  // keep-alive messages on the connection.
	 159  func (c *TCPConn) SetKeepAlive(keepalive bool) error {
	 160  	if !c.ok() {
	 161  		return syscall.EINVAL
	 162  	}
	 163  	if err := setKeepAlive(c.fd, keepalive); err != nil {
	 164  		return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 165  	}
	 166  	return nil
	 167  }
	 168  
	 169  // SetKeepAlivePeriod sets period between keep-alives.
	 170  func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
	 171  	if !c.ok() {
	 172  		return syscall.EINVAL
	 173  	}
	 174  	if err := setKeepAlivePeriod(c.fd, d); err != nil {
	 175  		return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 176  	}
	 177  	return nil
	 178  }
	 179  
	 180  // SetNoDelay controls whether the operating system should delay
	 181  // packet transmission in hopes of sending fewer packets (Nagle's
	 182  // algorithm).	The default is true (no delay), meaning that data is
	 183  // sent as soon as possible after a Write.
	 184  func (c *TCPConn) SetNoDelay(noDelay bool) error {
	 185  	if !c.ok() {
	 186  		return syscall.EINVAL
	 187  	}
	 188  	if err := setNoDelay(c.fd, noDelay); err != nil {
	 189  		return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	 190  	}
	 191  	return nil
	 192  }
	 193  
	 194  func newTCPConn(fd *netFD) *TCPConn {
	 195  	c := &TCPConn{conn{fd}}
	 196  	setNoDelay(c.fd, true)
	 197  	return c
	 198  }
	 199  
	 200  // DialTCP acts like Dial for TCP networks.
	 201  //
	 202  // The network must be a TCP network name; see func Dial for details.
	 203  //
	 204  // If laddr is nil, a local address is automatically chosen.
	 205  // If the IP field of raddr is nil or an unspecified IP address, the
	 206  // local system is assumed.
	 207  func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
	 208  	switch network {
	 209  	case "tcp", "tcp4", "tcp6":
	 210  	default:
	 211  		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
	 212  	}
	 213  	if raddr == nil {
	 214  		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
	 215  	}
	 216  	sd := &sysDialer{network: network, address: raddr.String()}
	 217  	c, err := sd.dialTCP(context.Background(), laddr, raddr)
	 218  	if err != nil {
	 219  		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
	 220  	}
	 221  	return c, nil
	 222  }
	 223  
	 224  // TCPListener is a TCP network listener. Clients should typically
	 225  // use variables of type Listener instead of assuming TCP.
	 226  type TCPListener struct {
	 227  	fd *netFD
	 228  	lc ListenConfig
	 229  }
	 230  
	 231  // SyscallConn returns a raw network connection.
	 232  // This implements the syscall.Conn interface.
	 233  //
	 234  // The returned RawConn only supports calling Control. Read and
	 235  // Write return an error.
	 236  func (l *TCPListener) SyscallConn() (syscall.RawConn, error) {
	 237  	if !l.ok() {
	 238  		return nil, syscall.EINVAL
	 239  	}
	 240  	return newRawListener(l.fd)
	 241  }
	 242  
	 243  // AcceptTCP accepts the next incoming call and returns the new
	 244  // connection.
	 245  func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
	 246  	if !l.ok() {
	 247  		return nil, syscall.EINVAL
	 248  	}
	 249  	c, err := l.accept()
	 250  	if err != nil {
	 251  		return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	 252  	}
	 253  	return c, nil
	 254  }
	 255  
	 256  // Accept implements the Accept method in the Listener interface; it
	 257  // waits for the next call and returns a generic Conn.
	 258  func (l *TCPListener) Accept() (Conn, error) {
	 259  	if !l.ok() {
	 260  		return nil, syscall.EINVAL
	 261  	}
	 262  	c, err := l.accept()
	 263  	if err != nil {
	 264  		return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	 265  	}
	 266  	return c, nil
	 267  }
	 268  
	 269  // Close stops listening on the TCP address.
	 270  // Already Accepted connections are not closed.
	 271  func (l *TCPListener) Close() error {
	 272  	if !l.ok() {
	 273  		return syscall.EINVAL
	 274  	}
	 275  	if err := l.close(); err != nil {
	 276  		return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	 277  	}
	 278  	return nil
	 279  }
	 280  
	 281  // Addr returns the listener's network address, a *TCPAddr.
	 282  // The Addr returned is shared by all invocations of Addr, so
	 283  // do not modify it.
	 284  func (l *TCPListener) Addr() Addr { return l.fd.laddr }
	 285  
	 286  // SetDeadline sets the deadline associated with the listener.
	 287  // A zero time value disables the deadline.
	 288  func (l *TCPListener) SetDeadline(t time.Time) error {
	 289  	if !l.ok() {
	 290  		return syscall.EINVAL
	 291  	}
	 292  	if err := l.fd.pfd.SetDeadline(t); err != nil {
	 293  		return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	 294  	}
	 295  	return nil
	 296  }
	 297  
	 298  // File returns a copy of the underlying os.File.
	 299  // It is the caller's responsibility to close f when finished.
	 300  // Closing l does not affect f, and closing f does not affect l.
	 301  //
	 302  // The returned os.File's file descriptor is different from the
	 303  // connection's. Attempting to change properties of the original
	 304  // using this duplicate may or may not have the desired effect.
	 305  func (l *TCPListener) File() (f *os.File, err error) {
	 306  	if !l.ok() {
	 307  		return nil, syscall.EINVAL
	 308  	}
	 309  	f, err = l.file()
	 310  	if err != nil {
	 311  		return nil, &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	 312  	}
	 313  	return
	 314  }
	 315  
	 316  // ListenTCP acts like Listen for TCP networks.
	 317  //
	 318  // The network must be a TCP network name; see func Dial for details.
	 319  //
	 320  // If the IP field of laddr is nil or an unspecified IP address,
	 321  // ListenTCP listens on all available unicast and anycast IP addresses
	 322  // of the local system.
	 323  // If the Port field of laddr is 0, a port number is automatically
	 324  // chosen.
	 325  func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error) {
	 326  	switch network {
	 327  	case "tcp", "tcp4", "tcp6":
	 328  	default:
	 329  		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
	 330  	}
	 331  	if laddr == nil {
	 332  		laddr = &TCPAddr{}
	 333  	}
	 334  	sl := &sysListener{network: network, address: laddr.String()}
	 335  	ln, err := sl.listenTCP(context.Background(), laddr)
	 336  	if err != nil {
	 337  		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
	 338  	}
	 339  	return ln, nil
	 340  }
	 341  
	 342  // roundDurationUp rounds d to the next multiple of to.
	 343  func roundDurationUp(d time.Duration, to time.Duration) time.Duration {
	 344  	return (d + to - 1) / to
	 345  }
	 346  

View as plain text