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

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

Issue 2309043: code review 2309043: Add SOCK_SEQPACKET support to Unix socket. (Closed)
Patch Set: code review 2309043: Add SOCK_SEQPACKET support to Unix socket. Created 14 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/server_test.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 // Unix domain sockets 5 // Unix domain sockets
6 6
7 package net 7 package net
8 8
9 import ( 9 import (
10 "os" 10 "os"
11 "syscall" 11 "syscall"
12 ) 12 )
13 13
14 func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) { 14 func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) {
15 var proto int 15 var proto int
16 switch net { 16 switch net {
17 default: 17 default:
18 return nil, UnknownNetworkError(net) 18 return nil, UnknownNetworkError(net)
19 case "unix": 19 case "unix":
20 proto = syscall.SOCK_STREAM 20 proto = syscall.SOCK_STREAM
21 case "unixgram": 21 case "unixgram":
22 proto = syscall.SOCK_DGRAM 22 proto = syscall.SOCK_DGRAM
23 case "unixpacket":
24 proto = syscall.SOCK_SEQPACKET
23 } 25 }
24 26
25 var la, ra syscall.Sockaddr 27 var la, ra syscall.Sockaddr
26 switch mode { 28 switch mode {
27 default: 29 default:
28 panic("unixSocket mode " + mode) 30 panic("unixSocket mode " + mode)
29 31
30 case "dial": 32 case "dial":
31 if laddr != nil { 33 if laddr != nil {
32 la = &syscall.SockaddrUnix{Name: laddr.Name} 34 la = &syscall.SockaddrUnix{Name: laddr.Name}
33 } 35 }
34 if raddr != nil { 36 if raddr != nil {
35 ra = &syscall.SockaddrUnix{Name: raddr.Name} 37 ra = &syscall.SockaddrUnix{Name: raddr.Name}
36 } else if proto != syscall.SOCK_DGRAM || laddr == nil { 38 } else if proto != syscall.SOCK_DGRAM || laddr == nil {
37 return nil, &OpError{Op: mode, Net: net, Error: errMissi ngAddress} 39 return nil, &OpError{Op: mode, Net: net, Error: errMissi ngAddress}
38 } 40 }
39 41
40 case "listen": 42 case "listen":
41 if laddr == nil { 43 if laddr == nil {
42 return nil, &OpError{mode, net, nil, errMissingAddress} 44 return nil, &OpError{mode, net, nil, errMissingAddress}
43 } 45 }
44 la = &syscall.SockaddrUnix{Name: laddr.Name} 46 la = &syscall.SockaddrUnix{Name: laddr.Name}
45 if raddr != nil { 47 if raddr != nil {
46 return nil, &OpError{Op: mode, Net: net, Addr: raddr, Er ror: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}} 48 return nil, &OpError{Op: mode, Net: net, Addr: raddr, Er ror: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}}
47 } 49 }
48 } 50 }
49 51
50 f := sockaddrToUnix 52 f := sockaddrToUnix
51 » if proto != syscall.SOCK_STREAM { 53 » if proto == syscall.SOCK_DGRAM {
52 f = sockaddrToUnixgram 54 f = sockaddrToUnixgram
55 } else if proto == syscall.SOCK_SEQPACKET {
56 f = sockaddrToUnixpacket
53 } 57 }
58
54 fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f) 59 fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
55 if oserr != nil { 60 if oserr != nil {
56 goto Error 61 goto Error
57 } 62 }
58 return fd, nil 63 return fd, nil
59 64
60 Error: 65 Error:
61 addr := raddr 66 addr := raddr
62 if mode == "listen" { 67 if mode == "listen" {
63 addr = laddr 68 addr = laddr
64 } 69 }
65 return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr} 70 return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr}
66 } 71 }
67 72
68 // UnixAddr represents the address of a Unix domain socket end point. 73 // UnixAddr represents the address of a Unix domain socket end point.
69 type UnixAddr struct { 74 type UnixAddr struct {
70 » Name string 75 » Name string
71 » Datagram bool 76 » Net string
72 } 77 }
73 78
74 func sockaddrToUnix(sa syscall.Sockaddr) Addr { 79 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
75 if s, ok := sa.(*syscall.SockaddrUnix); ok { 80 if s, ok := sa.(*syscall.SockaddrUnix); ok {
76 » » return &UnixAddr{s.Name, false} 81 » » return &UnixAddr{s.Name, "unix"}
77 } 82 }
78 return nil 83 return nil
79 } 84 }
80 85
81 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr { 86 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
82 if s, ok := sa.(*syscall.SockaddrUnix); ok { 87 if s, ok := sa.(*syscall.SockaddrUnix); ok {
83 » » return &UnixAddr{s.Name, true} 88 » » return &UnixAddr{s.Name, "unixgram"}
84 } 89 }
85 return nil 90 return nil
86 } 91 }
87 92
93 func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
94 if s, ok := sa.(*syscall.SockaddrUnix); ok {
95 return &UnixAddr{s.Name, "unixpacket"}
96 }
97 return nil
98 }
99
100 func protoToNet(proto int) string {
101 switch proto {
102 case syscall.SOCK_STREAM:
103 return "unix"
104 case syscall.SOCK_SEQPACKET:
105 return "unixpacket"
106 case syscall.SOCK_DGRAM:
107 return "unixgram"
108 default:
109 panic("protoToNet unknown protocol")
110 }
111 return ""
112 }
113
88 // Network returns the address's network name, "unix" or "unixgram". 114 // Network returns the address's network name, "unix" or "unixgram".
89 func (a *UnixAddr) Network() string { 115 func (a *UnixAddr) Network() string {
90 » if a == nil || !a.Datagram { 116 » return a.Net
91 » » return "unix"
92 » }
93 » return "unixgram"
94 } 117 }
95 118
96 func (a *UnixAddr) String() string { 119 func (a *UnixAddr) String() string {
97 if a == nil { 120 if a == nil {
98 return "<nil>" 121 return "<nil>"
99 } 122 }
100 return a.Name 123 return a.Name
101 } 124 }
102 125
103 func (a *UnixAddr) toAddr() Addr { 126 func (a *UnixAddr) toAddr() Addr {
104 if a == nil { // nil *UnixAddr 127 if a == nil { // nil *UnixAddr
105 return nil // nil interface 128 return nil // nil interface
106 } 129 }
107 return a 130 return a
108 } 131 }
109 132
110 // ResolveUnixAddr parses addr as a Unix domain socket address. 133 // ResolveUnixAddr parses addr as a Unix domain socket address.
111 // The string net gives the network name, "unix" or "unixgram". 134 // The string net gives the network name, "unix", "unixgram" or
135 // "unixpacket".
112 func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) { 136 func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
113 var datagram bool
114 switch net { 137 switch net {
115 case "unix": 138 case "unix":
139 case "unixpacket":
116 case "unixgram": 140 case "unixgram":
117 datagram = true
118 default: 141 default:
119 return nil, UnknownNetworkError(net) 142 return nil, UnknownNetworkError(net)
120 } 143 }
121 » return &UnixAddr{addr, datagram}, nil 144 » return &UnixAddr{addr, net}, nil
122 } 145 }
123 146
124 // UnixConn is an implementation of the Conn interface 147 // UnixConn is an implementation of the Conn interface
125 // for connections to Unix domain sockets. 148 // for connections to Unix domain sockets.
126 type UnixConn struct { 149 type UnixConn struct {
127 fd *netFD 150 fd *netFD
128 } 151 }
129 152
130 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} } 153 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} }
131 154
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // ReadFromUnix can be made to time out and return 250 // ReadFromUnix can be made to time out and return
228 // an error with Timeout() == true after a fixed time limit; 251 // an error with Timeout() == true after a fixed time limit;
229 // see SetTimeout and SetReadTimeout. 252 // see SetTimeout and SetReadTimeout.
230 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) { 253 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) {
231 if !c.ok() { 254 if !c.ok() {
232 return 0, nil, os.EINVAL 255 return 0, nil, os.EINVAL
233 } 256 }
234 n, sa, err := c.fd.ReadFrom(b) 257 n, sa, err := c.fd.ReadFrom(b)
235 switch sa := sa.(type) { 258 switch sa := sa.(type) {
236 case *syscall.SockaddrUnix: 259 case *syscall.SockaddrUnix:
237 » » addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM} 260 » » addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
238 } 261 }
239 return 262 return
240 } 263 }
241 264
242 // ReadFrom implements the net.PacketConn ReadFrom method. 265 // ReadFrom implements the net.PacketConn ReadFrom method.
243 func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { 266 func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
244 if !c.ok() { 267 if !c.ok() {
245 return 0, nil, os.EINVAL 268 return 0, nil, os.EINVAL
246 } 269 }
247 n, uaddr, err := c.ReadFromUnix(b) 270 n, uaddr, err := c.ReadFromUnix(b)
248 return n, uaddr.toAddr(), err 271 return n, uaddr.toAddr(), err
249 } 272 }
250 273
251 // WriteToUnix writes a packet to addr via c, copying the payload from b. 274 // WriteToUnix writes a packet to addr via c, copying the payload from b.
252 // 275 //
253 // WriteToUnix can be made to time out and return 276 // WriteToUnix can be made to time out and return
254 // an error with Timeout() == true after a fixed time limit; 277 // an error with Timeout() == true after a fixed time limit;
255 // see SetTimeout and SetWriteTimeout. 278 // see SetTimeout and SetWriteTimeout.
256 // On packet-oriented connections, write timeouts are rare. 279 // On packet-oriented connections, write timeouts are rare.
257 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) { 280 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
258 if !c.ok() { 281 if !c.ok() {
259 return 0, os.EINVAL 282 return 0, os.EINVAL
260 } 283 }
261 » if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) { 284 » if addr.Net != protoToNet(c.fd.proto) {
262 return 0, os.EAFNOSUPPORT 285 return 0, os.EAFNOSUPPORT
263 } 286 }
264 sa := &syscall.SockaddrUnix{Name: addr.Name} 287 sa := &syscall.SockaddrUnix{Name: addr.Name}
265 return c.fd.WriteTo(b, sa) 288 return c.fd.WriteTo(b, sa)
266 } 289 }
267 290
268 // WriteTo implements the net.PacketConn WriteTo method. 291 // WriteTo implements the net.PacketConn WriteTo method.
269 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { 292 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
270 if !c.ok() { 293 if !c.ok() {
271 return 0, os.EINVAL 294 return 0, os.EINVAL
272 } 295 }
273 a, ok := addr.(*UnixAddr) 296 a, ok := addr.(*UnixAddr)
274 if !ok { 297 if !ok {
275 return 0, &OpError{"writeto", "unix", addr, os.EINVAL} 298 return 0, &OpError{"writeto", "unix", addr, os.EINVAL}
276 } 299 }
277 return c.WriteToUnix(b, a) 300 return c.WriteToUnix(b, a)
278 } 301 }
279 302
280 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd r, err os.Error) { 303 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd r, err os.Error) {
281 if !c.ok() { 304 if !c.ok() {
282 return 0, 0, 0, nil, os.EINVAL 305 return 0, 0, 0, nil, os.EINVAL
283 } 306 }
284 n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob) 307 n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
285 switch sa := sa.(type) { 308 switch sa := sa.(type) {
286 case *syscall.SockaddrUnix: 309 case *syscall.SockaddrUnix:
287 » » addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM} 310 » » addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
288 } 311 }
289 return 312 return
290 } 313 }
291 314
292 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) { 315 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) {
293 if !c.ok() { 316 if !c.ok() {
294 return 0, 0, os.EINVAL 317 return 0, 0, os.EINVAL
295 } 318 }
296 if addr != nil { 319 if addr != nil {
297 » » if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) { 320 » » if addr.Net != protoToNet(c.fd.proto) {
298 return 0, 0, os.EAFNOSUPPORT 321 return 0, 0, os.EAFNOSUPPORT
299 } 322 }
300 sa := &syscall.SockaddrUnix{Name: addr.Name} 323 sa := &syscall.SockaddrUnix{Name: addr.Name}
301 return c.fd.WriteMsg(b, oob, sa) 324 return c.fd.WriteMsg(b, oob, sa)
302 } 325 }
303 return c.fd.WriteMsg(b, oob, nil) 326 return c.fd.WriteMsg(b, oob, nil)
304 } 327 }
305 328
306 // File returns a copy of the underlying os.File, set to blocking mode. 329 // File returns a copy of the underlying os.File, set to blocking mode.
307 // It is the caller's responsibility to close f when finished. 330 // It is the caller's responsibility to close f when finished.
(...skipping 15 matching lines...) Expand all
323 // Clients should typically use variables of type Listener 346 // Clients should typically use variables of type Listener
324 // instead of assuming Unix domain sockets. 347 // instead of assuming Unix domain sockets.
325 type UnixListener struct { 348 type UnixListener struct {
326 fd *netFD 349 fd *netFD
327 path string 350 path string
328 } 351 }
329 352
330 // ListenUnix announces on the Unix domain socket laddr and returns a Unix liste ner. 353 // ListenUnix announces on the Unix domain socket laddr and returns a Unix liste ner.
331 // Net must be "unix" (stream sockets). 354 // Net must be "unix" (stream sockets).
332 func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) { 355 func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
333 » if net != "unix" && net != "unixgram" { 356 » if net != "unix" && net != "unixgram" && net != "unixpacket" {
334 return nil, UnknownNetworkError(net) 357 return nil, UnknownNetworkError(net)
335 } 358 }
336 if laddr != nil { 359 if laddr != nil {
337 » » laddr = &UnixAddr{laddr.Name, net == "unixgram"} // make our own copy 360 » » laddr = &UnixAddr{laddr.Name, net} // make our own copy
338 } 361 }
339 fd, err := unixSocket(net, laddr, nil, "listen") 362 fd, err := unixSocket(net, laddr, nil, "listen")
340 if err != nil { 363 if err != nil {
341 return nil, err 364 return nil, err
342 } 365 }
343 e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog()); 366 e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
344 if e1 != 0 { 367 if e1 != 0 {
345 syscall.Close(fd.sysfd) 368 syscall.Close(fd.sysfd)
346 return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err or: os.Errno(e1)} 369 return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err or: os.Errno(e1)}
347 } 370 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 } 440 }
418 if laddr == nil { 441 if laddr == nil {
419 return nil, &OpError{"listen", "unixgram", nil, errMissingAddres s} 442 return nil, &OpError{"listen", "unixgram", nil, errMissingAddres s}
420 } 443 }
421 fd, e := unixSocket(net, laddr, nil, "listen") 444 fd, e := unixSocket(net, laddr, nil, "listen")
422 if e != nil { 445 if e != nil {
423 return nil, e 446 return nil, e
424 } 447 }
425 return newUDPConn(fd), nil 448 return newUDPConn(fd), nil
426 } 449 }
OLDNEW
« no previous file with comments | « src/pkg/net/server_test.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