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.
14 // TCPConn is an implementation of the Conn interface for TCP network
20 func newTCPConn(fd
*netFD
) *TCPConn
{
21 return &TCPConn
{conn
{fd
}}
24 // ReadFrom implements the io.ReaderFrom ReadFrom method.
25 func (c
*TCPConn
) ReadFrom(r io
.Reader
) (int64, error
) {
26 n
, err
:= genericReadFrom(c
, r
)
27 if err
!= nil && err
!= io
.EOF
{
28 err
= &OpError
{Op
: "read", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: err
}
33 // CloseRead shuts down the reading side of the TCP connection.
34 // Most callers should just use Close.
35 func (c
*TCPConn
) CloseRead() error
{
39 err
:= c
.fd
.closeRead()
41 err
= &OpError
{Op
: "close", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: err
}
46 // CloseWrite shuts down the writing side of the TCP connection.
47 // Most callers should just use Close.
48 func (c
*TCPConn
) CloseWrite() error
{
52 err
:= c
.fd
.closeWrite()
54 err
= &OpError
{Op
: "close", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: err
}
59 // SetLinger sets the behavior of Close on a connection which still
60 // has data waiting to be sent or to be acknowledged.
62 // If sec < 0 (the default), the operating system finishes sending the
63 // data in the background.
65 // If sec == 0, the operating system discards any unsent or
66 // unacknowledged data.
68 // If sec > 0, the data is sent in the background as with sec < 0. On
69 // some operating systems after sec seconds have elapsed any remaining
70 // unsent data may be discarded.
71 func (c
*TCPConn
) SetLinger(sec
int) error
{
72 return &OpError
{Op
: "set", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: syscall
.EPLAN9
}
75 // SetKeepAlive sets whether the operating system should send
76 // keepalive messages on the connection.
77 func (c
*TCPConn
) SetKeepAlive(keepalive
bool) error
{
81 if err
:= setKeepAlive(c
.fd
, keepalive
); err
!= nil {
82 return &OpError
{Op
: "set", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: err
}
87 // SetKeepAlivePeriod sets period between keep alives.
88 func (c
*TCPConn
) SetKeepAlivePeriod(d time
.Duration
) error
{
92 if err
:= setKeepAlivePeriod(c
.fd
, d
); err
!= nil {
93 return &OpError
{Op
: "set", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: err
}
98 // SetNoDelay controls whether the operating system should delay
99 // packet transmission in hopes of sending fewer packets (Nagle's
100 // algorithm). The default is true (no delay), meaning that data is
101 // sent as soon as possible after a Write.
102 func (c
*TCPConn
) SetNoDelay(noDelay
bool) error
{
103 return &OpError
{Op
: "set", Net
: c
.fd
.dir
, Source
: c
.fd
.laddr
, Addr
: c
.fd
.raddr
, Err
: syscall
.EPLAN9
}
106 // DialTCP connects to the remote address raddr on the network net,
107 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is
108 // used as the local address for the connection.
109 func DialTCP(net
string, laddr
, raddr
*TCPAddr
) (*TCPConn
, error
) {
110 return dialTCP(net
, laddr
, raddr
, noDeadline
, noCancel
)
113 func dialTCP(net
string, laddr
, raddr
*TCPAddr
, deadline time
.Time
, cancel
<-chan struct{}) (*TCPConn
, error
) {
114 if !deadline
.IsZero() {
115 panic("net.dialTCP: deadline not implemented on Plan 9")
117 // TODO(bradfitz,0intro): also use the cancel channel.
119 case "tcp", "tcp4", "tcp6":
121 return nil, &OpError
{Op
: "dial", Net
: net
, Source
: laddr
.opAddr(), Addr
: raddr
.opAddr(), Err
: UnknownNetworkError(net
)}
124 return nil, &OpError
{Op
: "dial", Net
: net
, Source
: laddr
.opAddr(), Addr
: nil, Err
: errMissingAddress
}
126 fd
, err
:= dialPlan9(net
, laddr
, raddr
)
130 return newTCPConn(fd
), nil
133 // TCPListener is a TCP network listener. Clients should typically
134 // use variables of type Listener instead of assuming TCP.
135 type TCPListener
struct {
139 // AcceptTCP accepts the next incoming call and returns the new
141 func (l
*TCPListener
) AcceptTCP() (*TCPConn
, error
) {
142 if l
== nil || l
.fd
== nil || l
.fd
.ctl
== nil {
143 return nil, syscall
.EINVAL
145 fd
, err
:= l
.fd
.acceptPlan9()
149 return newTCPConn(fd
), nil
152 // Accept implements the Accept method in the Listener interface; it
153 // waits for the next call and returns a generic Conn.
154 func (l
*TCPListener
) Accept() (Conn
, error
) {
155 if l
== nil || l
.fd
== nil || l
.fd
.ctl
== nil {
156 return nil, syscall
.EINVAL
158 c
, err
:= l
.AcceptTCP()
165 // Close stops listening on the TCP address.
166 // Already Accepted connections are not closed.
167 func (l
*TCPListener
) Close() error
{
168 if l
== nil || l
.fd
== nil || l
.fd
.ctl
== nil {
169 return syscall
.EINVAL
171 if _
, err
:= l
.fd
.ctl
.WriteString("hangup"); err
!= nil {
173 return &OpError
{Op
: "close", Net
: l
.fd
.dir
, Source
: nil, Addr
: l
.fd
.laddr
, Err
: err
}
175 err
:= l
.fd
.ctl
.Close()
177 err
= &OpError
{Op
: "close", Net
: l
.fd
.dir
, Source
: nil, Addr
: l
.fd
.laddr
, Err
: err
}
182 // Addr returns the listener's network address, a *TCPAddr.
183 // The Addr returned is shared by all invocations of Addr, so
185 func (l
*TCPListener
) Addr() Addr
{ return l
.fd
.laddr
}
187 // SetDeadline sets the deadline associated with the listener.
188 // A zero time value disables the deadline.
189 func (l
*TCPListener
) SetDeadline(t time
.Time
) error
{
190 if l
== nil || l
.fd
== nil || l
.fd
.ctl
== nil {
191 return syscall
.EINVAL
193 if err
:= l
.fd
.setDeadline(t
); err
!= nil {
194 return &OpError
{Op
: "set", Net
: l
.fd
.dir
, Source
: nil, Addr
: l
.fd
.laddr
, Err
: err
}
199 // File returns a copy of the underlying os.File, set to blocking
200 // mode. It is the caller's responsibility to close f when finished.
201 // Closing l does not affect f, and closing f does not affect l.
203 // The returned os.File's file descriptor is different from the
204 // connection's. Attempting to change properties of the original
205 // using this duplicate may or may not have the desired effect.
206 func (l
*TCPListener
) File() (f
*os
.File
, err error
) {
209 err
= &OpError
{Op
: "file", Net
: l
.fd
.dir
, Source
: nil, Addr
: l
.fd
.laddr
, Err
: err
}
214 // ListenTCP announces on the TCP address laddr and returns a TCP
215 // listener. Net must be "tcp", "tcp4", or "tcp6". If laddr has a
216 // port of 0, ListenTCP will choose an available port. The caller can
217 // use the Addr method of TCPListener to retrieve the chosen address.
218 func ListenTCP(net
string, laddr
*TCPAddr
) (*TCPListener
, error
) {
220 case "tcp", "tcp4", "tcp6":
222 return nil, &OpError
{Op
: "listen", Net
: net
, Source
: nil, Addr
: laddr
.opAddr(), Err
: UnknownNetworkError(net
)}
227 fd
, err
:= listenPlan9(net
, laddr
)
231 return &TCPListener
{fd
}, nil