Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(38)

Side by Side Diff: src/pkg/net/unixsock_posix.go

Issue 6937059: code review 6937059: net: change ListenUnixgram signature to return UnixConn... (Closed)
Patch Set: diff -r 9e8d16052155 https://code.google.com/p/go Created 11 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/net/unixsock_plan9.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin freebsd linux netbsd openbsd windows 5 // +build darwin freebsd linux netbsd openbsd windows
6 6
7 // Unix domain sockets 7 // Unix domain sockets
8 8
9 package net 9 package net
10 10
11 import ( 11 import (
12 "errors"
12 "os" 13 "os"
13 "syscall" 14 "syscall"
14 "time" 15 "time"
15 ) 16 )
16 17
17 func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T ime) (fd *netFD, err error) { 18 func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T ime) (*netFD, error) {
18 var sotype int 19 var sotype int
19 switch net { 20 switch net {
20 default:
21 return nil, UnknownNetworkError(net)
22 case "unix": 21 case "unix":
23 sotype = syscall.SOCK_STREAM 22 sotype = syscall.SOCK_STREAM
24 case "unixgram": 23 case "unixgram":
25 sotype = syscall.SOCK_DGRAM 24 sotype = syscall.SOCK_DGRAM
26 case "unixpacket": 25 case "unixpacket":
27 sotype = syscall.SOCK_SEQPACKET 26 sotype = syscall.SOCK_SEQPACKET
27 default:
28 return nil, UnknownNetworkError(net)
28 } 29 }
29 30
30 var la, ra syscall.Sockaddr 31 var la, ra syscall.Sockaddr
31 switch mode { 32 switch mode {
32 default:
33 panic("unixSocket mode " + mode)
34
35 case "dial": 33 case "dial":
36 if laddr != nil { 34 if laddr != nil {
37 la = &syscall.SockaddrUnix{Name: laddr.Name} 35 la = &syscall.SockaddrUnix{Name: laddr.Name}
38 } 36 }
39 if raddr != nil { 37 if raddr != nil {
40 ra = &syscall.SockaddrUnix{Name: raddr.Name} 38 ra = &syscall.SockaddrUnix{Name: raddr.Name}
41 } else if sotype != syscall.SOCK_DGRAM || laddr == nil { 39 } else if sotype != syscall.SOCK_DGRAM || laddr == nil {
42 return nil, &OpError{Op: mode, Net: net, Err: errMissing Address} 40 return nil, &OpError{Op: mode, Net: net, Err: errMissing Address}
43 } 41 }
44
45 case "listen": 42 case "listen":
46 if laddr == nil {
47 return nil, &OpError{mode, net, nil, errMissingAddress}
48 }
49 la = &syscall.SockaddrUnix{Name: laddr.Name} 43 la = &syscall.SockaddrUnix{Name: laddr.Name}
50 » » if raddr != nil { 44 » default:
51 » » » return nil, &OpError{Op: mode, Net: net, Addr: raddr, Er r: &AddrError{Err: "unexpected remote address", Addr: raddr.String()}} 45 » » return nil, errors.New("unknown mode: " + mode)
52 » » }
53 } 46 }
54 47
55 f := sockaddrToUnix 48 f := sockaddrToUnix
56 if sotype == syscall.SOCK_DGRAM { 49 if sotype == syscall.SOCK_DGRAM {
57 f = sockaddrToUnixgram 50 f = sockaddrToUnixgram
58 } else if sotype == syscall.SOCK_SEQPACKET { 51 } else if sotype == syscall.SOCK_SEQPACKET {
59 f = sockaddrToUnixpacket 52 f = sockaddrToUnixpacket
60 } 53 }
61 54
62 » fd, err = socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, deadlin e, f) 55 » fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, deadli ne, f)
63 if err != nil { 56 if err != nil {
64 » » goto Error 57 » » goto error
65 } 58 }
66 return fd, nil 59 return fd, nil
67 60
68 Error: 61 error:
69 addr := raddr 62 addr := raddr
70 » if mode == "listen" { 63 » switch mode {
64 » case "listen":
71 addr = laddr 65 addr = laddr
72 } 66 }
73 return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err} 67 return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err}
74 } 68 }
75 69
76 func sockaddrToUnix(sa syscall.Sockaddr) Addr { 70 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
77 if s, ok := sa.(*syscall.SockaddrUnix); ok { 71 if s, ok := sa.(*syscall.SockaddrUnix); ok {
78 return &UnixAddr{s.Name, "unix"} 72 return &UnixAddr{s.Name, "unix"}
79 } 73 }
80 return nil 74 return nil
(...skipping 20 matching lines...) Expand all
101 case syscall.SOCK_SEQPACKET: 95 case syscall.SOCK_SEQPACKET:
102 return "unixpacket" 96 return "unixpacket"
103 case syscall.SOCK_DGRAM: 97 case syscall.SOCK_DGRAM:
104 return "unixgram" 98 return "unixgram"
105 default: 99 default:
106 panic("sotypeToNet unknown socket type") 100 panic("sotypeToNet unknown socket type")
107 } 101 }
108 return "" 102 return ""
109 } 103 }
110 104
111 // UnixConn is an implementation of the Conn interface 105 // UnixConn is an implementation of the Conn interface for connections
112 // for connections to Unix domain sockets. 106 // to Unix domain sockets.
113 type UnixConn struct { 107 type UnixConn struct {
114 conn 108 conn
115 } 109 }
116 110
117 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} } 111 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
118 112
119 // ReadFromUnix reads a packet from c, copying the payload into b. 113 // ReadFromUnix reads a packet from c, copying the payload into b. It
120 // It returns the number of bytes copied into b and the source address 114 // returns the number of bytes copied into b and the source address of
121 // of the packet. 115 // the packet.
122 // 116 //
123 // ReadFromUnix can be made to time out and return 117 // ReadFromUnix can be made to time out and return an error with
124 // an error with Timeout() == true after a fixed time limit; 118 // Timeout() == true after a fixed time limit; see SetDeadline and
125 // see SetDeadline and SetReadDeadline. 119 // SetReadDeadline.
126 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) { 120 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
127 if !c.ok() { 121 if !c.ok() {
128 return 0, nil, syscall.EINVAL 122 return 0, nil, syscall.EINVAL
129 } 123 }
130 n, sa, err := c.fd.ReadFrom(b) 124 n, sa, err := c.fd.ReadFrom(b)
131 switch sa := sa.(type) { 125 switch sa := sa.(type) {
132 case *syscall.SockaddrUnix: 126 case *syscall.SockaddrUnix:
133 addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)} 127 addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
134 } 128 }
135 return 129 return
136 } 130 }
137 131
138 // ReadFrom implements the PacketConn ReadFrom method. 132 // ReadFrom implements the PacketConn ReadFrom method.
139 func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { 133 func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
140 if !c.ok() { 134 if !c.ok() {
141 return 0, nil, syscall.EINVAL 135 return 0, nil, syscall.EINVAL
142 } 136 }
143 n, uaddr, err := c.ReadFromUnix(b) 137 n, uaddr, err := c.ReadFromUnix(b)
144 return n, uaddr.toAddr(), err 138 return n, uaddr.toAddr(), err
145 } 139 }
146 140
141 // ReadMsgUnix reads a packet from c, copying the payload into b and
142 // the associated out-of-band data into oob. It returns the number of
143 // bytes copied into b, the number of bytes copied into oob, the flags
144 // that were set on the packet, and the source address of the packet.
145 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd r, err error) {
146 if !c.ok() {
147 return 0, 0, 0, nil, syscall.EINVAL
148 }
149 n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
150 switch sa := sa.(type) {
151 case *syscall.SockaddrUnix:
152 addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
153 }
154 return
155 }
156
147 // WriteToUnix writes a packet to addr via c, copying the payload from b. 157 // WriteToUnix writes a packet to addr via c, copying the payload from b.
148 // 158 //
149 // WriteToUnix can be made to time out and return 159 // WriteToUnix can be made to time out and return an error with
150 // an error with Timeout() == true after a fixed time limit; 160 // Timeout() == true after a fixed time limit; see SetDeadline and
151 // see SetDeadline and SetWriteDeadline. 161 // SetWriteDeadline. On packet-oriented connections, write timeouts
152 // On packet-oriented connections, write timeouts are rare. 162 // are rare.
153 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) { 163 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
154 if !c.ok() { 164 if !c.ok() {
155 return 0, syscall.EINVAL 165 return 0, syscall.EINVAL
156 } 166 }
157 if addr.Net != sotypeToNet(c.fd.sotype) { 167 if addr.Net != sotypeToNet(c.fd.sotype) {
158 return 0, syscall.EAFNOSUPPORT 168 return 0, syscall.EAFNOSUPPORT
159 } 169 }
160 sa := &syscall.SockaddrUnix{Name: addr.Name} 170 sa := &syscall.SockaddrUnix{Name: addr.Name}
161 return c.fd.WriteTo(b, sa) 171 return c.fd.WriteTo(b, sa)
162 } 172 }
163 173
164 // WriteTo implements the PacketConn WriteTo method. 174 // WriteTo implements the PacketConn WriteTo method.
165 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { 175 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
166 if !c.ok() { 176 if !c.ok() {
167 return 0, syscall.EINVAL 177 return 0, syscall.EINVAL
168 } 178 }
169 a, ok := addr.(*UnixAddr) 179 a, ok := addr.(*UnixAddr)
170 if !ok { 180 if !ok {
171 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL} 181 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
172 } 182 }
173 return c.WriteToUnix(b, a) 183 return c.WriteToUnix(b, a)
174 } 184 }
175 185
176 // ReadMsgUnix reads a packet from c, copying the payload into b 186 // WriteMsgUnix writes a packet to addr via c, copying the payload
177 // and the associated out-of-band data into oob. 187 // from b and the associated out-of-band data from oob. It returns
178 // It returns the number of bytes copied into b, the number of 188 // the number of payload and out-of-band bytes written.
179 // bytes copied into oob, the flags that were set on the packet,
180 // and the source address of the packet.
181 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd r, err error) {
182 » if !c.ok() {
183 » » return 0, 0, 0, nil, syscall.EINVAL
184 » }
185 » n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
186 » switch sa := sa.(type) {
187 » case *syscall.SockaddrUnix:
188 » » addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
189 » }
190 » return
191 }
192
193 // WriteMsgUnix writes a packet to addr via c, copying the payload from b
194 // and the associated out-of-band data from oob. It returns the number
195 // of payload and out-of-band bytes written.
196 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) { 189 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
197 if !c.ok() { 190 if !c.ok() {
198 return 0, 0, syscall.EINVAL 191 return 0, 0, syscall.EINVAL
199 } 192 }
200 if addr != nil { 193 if addr != nil {
201 if addr.Net != sotypeToNet(c.fd.sotype) { 194 if addr.Net != sotypeToNet(c.fd.sotype) {
202 return 0, 0, syscall.EAFNOSUPPORT 195 return 0, 0, syscall.EAFNOSUPPORT
203 } 196 }
204 sa := &syscall.SockaddrUnix{Name: addr.Name} 197 sa := &syscall.SockaddrUnix{Name: addr.Name}
205 return c.fd.WriteMsg(b, oob, sa) 198 return c.fd.WriteMsg(b, oob, sa)
(...skipping 13 matching lines...) Expand all
219 // CloseWrite shuts down the writing side of the Unix domain connection. 212 // CloseWrite shuts down the writing side of the Unix domain connection.
220 // Most callers should just use Close. 213 // Most callers should just use Close.
221 func (c *UnixConn) CloseWrite() error { 214 func (c *UnixConn) CloseWrite() error {
222 if !c.ok() { 215 if !c.ok() {
223 return syscall.EINVAL 216 return syscall.EINVAL
224 } 217 }
225 return c.fd.CloseWrite() 218 return c.fd.CloseWrite()
226 } 219 }
227 220
228 // DialUnix connects to the remote address raddr on the network net, 221 // DialUnix connects to the remote address raddr on the network net,
229 // which must be "unix" or "unixgram". If laddr is not nil, it is used 222 // which must be "unix", "unixgram" or "unixpacket". If laddr is not
230 // as the local address for the connection. 223 // nil, it is used as the local address for the connection.
231 func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) { 224 func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
232 return dialUnix(net, laddr, raddr, noDeadline) 225 return dialUnix(net, laddr, raddr, noDeadline)
233 } 226 }
234 227
235 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn , error) { 228 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn , error) {
229 switch net {
230 case "unix", "unixgram", "unixpacket":
231 default:
232 return nil, UnknownNetworkError(net)
233 }
236 fd, err := unixSocket(net, laddr, raddr, "dial", deadline) 234 fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
237 if err != nil { 235 if err != nil {
238 return nil, err 236 return nil, err
239 } 237 }
240 return newUnixConn(fd), nil 238 return newUnixConn(fd), nil
241 } 239 }
242 240
243 // UnixListener is a Unix domain socket listener. 241 // UnixListener is a Unix domain socket listener. Clients should
244 // Clients should typically use variables of type Listener 242 // typically use variables of type Listener instead of assuming Unix
245 // instead of assuming Unix domain sockets. 243 // domain sockets.
246 type UnixListener struct { 244 type UnixListener struct {
247 fd *netFD 245 fd *netFD
248 path string 246 path string
249 } 247 }
250 248
251 // ListenUnix announces on the Unix domain socket laddr and returns a Unix liste ner. 249 // ListenUnix announces on the Unix domain socket laddr and returns a
252 // Net must be "unix" (stream sockets). 250 // Unix listener. The network net must be "unix", "unixgram" or
251 // "unixpacket".
253 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) { 252 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
254 » if net != "unix" && net != "unixgram" && net != "unixpacket" { 253 » switch net {
254 » case "unix", "unixgram", "unixpacket":
255 » default:
255 return nil, UnknownNetworkError(net) 256 return nil, UnknownNetworkError(net)
256 } 257 }
257 » if laddr != nil { 258 » if laddr == nil {
258 » » laddr = &UnixAddr{laddr.Name, net} // make our own copy 259 » » return nil, &OpError{"listen", net, nil, errMissingAddress}
259 } 260 }
260 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline) 261 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
261 if err != nil { 262 if err != nil {
262 return nil, err 263 return nil, err
263 } 264 }
264 err = syscall.Listen(fd.sysfd, listenerBacklog) 265 err = syscall.Listen(fd.sysfd, listenerBacklog)
265 if err != nil { 266 if err != nil {
266 closesocket(fd.sysfd) 267 closesocket(fd.sysfd)
267 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: e rr} 268 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: e rr}
268 } 269 }
269 return &UnixListener{fd, laddr.Name}, nil 270 return &UnixListener{fd, laddr.Name}, nil
270 } 271 }
271 272
272 // AcceptUnix accepts the next incoming call and returns the new connection 273 // AcceptUnix accepts the next incoming call and returns the new
273 // and the remote address. 274 // connection and the remote address.
274 func (l *UnixListener) AcceptUnix() (*UnixConn, error) { 275 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
275 if l == nil || l.fd == nil { 276 if l == nil || l.fd == nil {
276 return nil, syscall.EINVAL 277 return nil, syscall.EINVAL
277 } 278 }
278 fd, err := l.fd.accept(sockaddrToUnix) 279 fd, err := l.fd.accept(sockaddrToUnix)
279 if err != nil { 280 if err != nil {
280 return nil, err 281 return nil, err
281 } 282 }
282 c := newUnixConn(fd) 283 c := newUnixConn(fd)
283 return c, nil 284 return c, nil
284 } 285 }
285 286
286 // Accept implements the Accept method in the Listener interface; 287 // Accept implements the Accept method in the Listener interface; it
287 // it waits for the next call and returns a generic Conn. 288 // waits for the next call and returns a generic Conn.
288 func (l *UnixListener) Accept() (c Conn, err error) { 289 func (l *UnixListener) Accept() (c Conn, err error) {
289 c1, err := l.AcceptUnix() 290 c1, err := l.AcceptUnix()
290 if err != nil { 291 if err != nil {
291 return nil, err 292 return nil, err
292 } 293 }
293 return c1, nil 294 return c1, nil
294 } 295 }
295 296
296 // Close stops listening on the Unix address. 297 // Close stops listening on the Unix address. Already accepted
297 // Already accepted connections are not closed. 298 // connections are not closed.
298 func (l *UnixListener) Close() error { 299 func (l *UnixListener) Close() error {
299 if l == nil || l.fd == nil { 300 if l == nil || l.fd == nil {
300 return syscall.EINVAL 301 return syscall.EINVAL
301 } 302 }
302 303
303 // The operating system doesn't clean up 304 // The operating system doesn't clean up
304 // the file that announcing created, so 305 // the file that announcing created, so
305 // we have to clean it up ourselves. 306 // we have to clean it up ourselves.
306 // There's a race here--we can't know for 307 // There's a race here--we can't know for
307 // sure whether someone else has come along 308 // sure whether someone else has come along
(...skipping 13 matching lines...) Expand all
321 322
322 // SetDeadline sets the deadline associated with the listener. 323 // SetDeadline sets the deadline associated with the listener.
323 // A zero time value disables the deadline. 324 // A zero time value disables the deadline.
324 func (l *UnixListener) SetDeadline(t time.Time) (err error) { 325 func (l *UnixListener) SetDeadline(t time.Time) (err error) {
325 if l == nil || l.fd == nil { 326 if l == nil || l.fd == nil {
326 return syscall.EINVAL 327 return syscall.EINVAL
327 } 328 }
328 return setDeadline(l.fd, t) 329 return setDeadline(l.fd, t)
329 } 330 }
330 331
331 // File returns a copy of the underlying os.File, set to blocking mode. 332 // File returns a copy of the underlying os.File, set to blocking
332 // It is the caller's responsibility to close f when finished. 333 // mode. It is the caller's responsibility to close f when finished.
333 // Closing l does not affect f, and closing f does not affect l. 334 // Closing l does not affect f, and closing f does not affect l.
334 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() } 335 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
335 336
336 // ListenUnixgram listens for incoming Unix datagram packets addressed to the 337 // ListenUnixgram listens for incoming Unix datagram packets addressed
337 // local address laddr. The returned connection c's ReadFrom 338 // to the local address laddr. The returned connection c's ReadFrom
338 // and WriteTo methods can be used to receive and send UDP 339 // and WriteTo methods can be used to receive and send packets with
339 // packets with per-packet addressing. The network net must be "unixgram". 340 // per-packet addressing. The network net must be "unixgram".
340 func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) { 341 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
341 switch net { 342 switch net {
342 case "unixgram": 343 case "unixgram":
343 default: 344 default:
344 return nil, UnknownNetworkError(net) 345 return nil, UnknownNetworkError(net)
345 } 346 }
346 if laddr == nil { 347 if laddr == nil {
347 return nil, &OpError{"listen", net, nil, errMissingAddress} 348 return nil, &OpError{"listen", net, nil, errMissingAddress}
348 } 349 }
349 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline) 350 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
350 if err != nil { 351 if err != nil {
351 return nil, err 352 return nil, err
352 } 353 }
353 » return newUDPConn(fd), nil 354 » return newUnixConn(fd), nil
354 } 355 }
OLDNEW
« no previous file with comments | « src/pkg/net/unixsock_plan9.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b