Source file src/pkg/net/tcpsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "io"
11 "os"
12 "syscall"
13 "time"
14 )
15
16
17
18
19
20
21 func sockaddrToTCP(sa syscall.Sockaddr) Addr {
22 switch sa := sa.(type) {
23 case *syscall.SockaddrInet4:
24 return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
25 case *syscall.SockaddrInet6:
26 return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
27 }
28 return nil
29 }
30
31 func (a *TCPAddr) family() int {
32 if a == nil || len(a.IP) <= IPv4len {
33 return syscall.AF_INET
34 }
35 if a.IP.To4() != nil {
36 return syscall.AF_INET
37 }
38 return syscall.AF_INET6
39 }
40
41 func (a *TCPAddr) isWildcard() bool {
42 if a == nil || a.IP == nil {
43 return true
44 }
45 return a.IP.IsUnspecified()
46 }
47
48 func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
49 return ipToSockaddr(family, a.IP, a.Port, a.Zone)
50 }
51
52 func (a *TCPAddr) toAddr() sockaddr {
53 if a == nil {
54 return nil
55 }
56 return a
57 }
58
59
60
61 type TCPConn struct {
62 conn
63 }
64
65 func newTCPConn(fd *netFD) *TCPConn {
66 c := &TCPConn{conn{fd}}
67 c.SetNoDelay(true)
68 return c
69 }
70
71
72 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
73 if n, err, handled := sendFile(c.fd, r); handled {
74 return n, err
75 }
76 return genericReadFrom(c, r)
77 }
78
79
80
81 func (c *TCPConn) CloseRead() error {
82 if !c.ok() {
83 return syscall.EINVAL
84 }
85 return c.fd.CloseRead()
86 }
87
88
89
90 func (c *TCPConn) CloseWrite() error {
91 if !c.ok() {
92 return syscall.EINVAL
93 }
94 return c.fd.CloseWrite()
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 func (c *TCPConn) SetLinger(sec int) error {
109 if !c.ok() {
110 return syscall.EINVAL
111 }
112 return setLinger(c.fd, sec)
113 }
114
115
116
117 func (c *TCPConn) SetKeepAlive(keepalive bool) error {
118 if !c.ok() {
119 return syscall.EINVAL
120 }
121 return setKeepAlive(c.fd, keepalive)
122 }
123
124
125
126
127
128 func (c *TCPConn) SetNoDelay(noDelay bool) error {
129 if !c.ok() {
130 return syscall.EINVAL
131 }
132 return setNoDelay(c.fd, noDelay)
133 }
134
135
136
137
138 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
139 switch net {
140 case "tcp", "tcp4", "tcp6":
141 default:
142 return nil, UnknownNetworkError(net)
143 }
144 if raddr == nil {
145 return nil, &OpError{"dial", net, nil, errMissingAddress}
146 }
147 return dialTCP(net, laddr, raddr, noDeadline)
148 }
149
150 func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
151 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
178 if err == nil {
179 fd.Close()
180 }
181 fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
182 }
183
184 if err != nil {
185 return nil, err
186 }
187 return newTCPConn(fd), nil
188 }
189
190 func selfConnect(fd *netFD, err error) bool {
191
192 if err != nil {
193 return false
194 }
195
196
197
198
199
200
201
202
203
204 if fd.laddr == nil || fd.raddr == nil {
205 return true
206 }
207 l := fd.laddr.(*TCPAddr)
208 r := fd.raddr.(*TCPAddr)
209 return l.Port == r.Port && l.IP.Equal(r.IP)
210 }
211
212 func spuriousENOTAVAIL(err error) bool {
213 e, ok := err.(*OpError)
214 return ok && e.Err == syscall.EADDRNOTAVAIL
215 }
216
217
218
219 type TCPListener struct {
220 fd *netFD
221 }
222
223
224
225 func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
226 if l == nil || l.fd == nil {
227 return nil, syscall.EINVAL
228 }
229 fd, err := l.fd.accept(sockaddrToTCP)
230 if err != nil {
231 return nil, err
232 }
233 return newTCPConn(fd), nil
234 }
235
236
237
238 func (l *TCPListener) Accept() (Conn, error) {
239 c, err := l.AcceptTCP()
240 if err != nil {
241 return nil, err
242 }
243 return c, nil
244 }
245
246
247
248 func (l *TCPListener) Close() error {
249 if l == nil || l.fd == nil {
250 return syscall.EINVAL
251 }
252 return l.fd.Close()
253 }
254
255
256 func (l *TCPListener) Addr() Addr { return l.fd.laddr }
257
258
259
260 func (l *TCPListener) SetDeadline(t time.Time) error {
261 if l == nil || l.fd == nil {
262 return syscall.EINVAL
263 }
264 return setDeadline(l.fd, t)
265 }
266
267
268
269
270
271
272
273
274 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
275
276
277
278
279
280 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
281 switch net {
282 case "tcp", "tcp4", "tcp6":
283 default:
284 return nil, UnknownNetworkError(net)
285 }
286 if laddr == nil {
287 laddr = &TCPAddr{}
288 }
289 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
290 if err != nil {
291 return nil, err
292 }
293 err = syscall.Listen(fd.sysfd, listenerBacklog)
294 if err != nil {
295 fd.Close()
296 return nil, &OpError{"listen", net, laddr, err}
297 }
298 return &TCPListener{fd}, nil
299 }
View as plain text