OLD | NEW |
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 // IP sockets stubs for Plan 9 | 5 // IP sockets stubs for Plan 9 |
6 | 6 |
7 package net | 7 package net |
8 | 8 |
9 import ( | 9 import ( |
10 "errors" | 10 "errors" |
11 "io" | |
12 "os" | 11 "os" |
13 "syscall" | |
14 "time" | |
15 ) | 12 ) |
16 | 13 |
17 // /sys/include/ape/sys/socket.h:/SOMAXCONN | 14 // /sys/include/ape/sys/socket.h:/SOMAXCONN |
18 var listenerBacklog = 5 | 15 var listenerBacklog = 5 |
19 | 16 |
20 // probeIPv6Stack returns two boolean values. If the first boolean | 17 // probeIPv6Stack returns two boolean values. If the first boolean |
21 // value is true, kernel supports basic IPv6 functionality. If the | 18 // value is true, kernel supports basic IPv6 functionality. If the |
22 // second boolean value is true, kernel supports IPv6 IPv4-mapping. | 19 // second boolean value is true, kernel supports IPv6 IPv4-mapping. |
23 func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { | 20 func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { |
24 return false, false | 21 return false, false |
25 } | 22 } |
26 | 23 |
27 var canCancelIO = true // used for testing current package | |
28 | |
29 func sysInit() { | |
30 } | |
31 | |
32 // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80). | 24 // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80). |
33 func parsePlan9Addr(s string) (ip IP, iport int, err error) { | 25 func parsePlan9Addr(s string) (ip IP, iport int, err error) { |
34 addr := IPv4zero // address contains port only | 26 addr := IPv4zero // address contains port only |
35 i := byteIndex(s, '!') | 27 i := byteIndex(s, '!') |
36 if i >= 0 { | 28 if i >= 0 { |
37 addr = ParseIP(s[:i]) | 29 addr = ParseIP(s[:i]) |
38 if addr == nil { | 30 if addr == nil { |
39 return nil, 0, errors.New("net: parsing IP failed") | 31 return nil, 0, errors.New("net: parsing IP failed") |
40 } | 32 } |
41 } | 33 } |
(...skipping 27 matching lines...) Expand all Loading... |
69 case "tcp": | 61 case "tcp": |
70 addr = &TCPAddr{ip, port} | 62 addr = &TCPAddr{ip, port} |
71 case "udp": | 63 case "udp": |
72 addr = &UDPAddr{ip, port} | 64 addr = &UDPAddr{ip, port} |
73 default: | 65 default: |
74 return nil, errors.New("unknown protocol " + proto) | 66 return nil, errors.New("unknown protocol " + proto) |
75 } | 67 } |
76 return addr, nil | 68 return addr, nil |
77 } | 69 } |
78 | 70 |
79 type plan9Conn struct { | |
80 proto, name, dir string | |
81 ctl, data *os.File | |
82 laddr, raddr Addr | |
83 } | |
84 | |
85 func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Con
n { | |
86 return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, l
addr, raddr} | |
87 } | |
88 | |
89 func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil } | |
90 | |
91 // Implementation of the Conn interface - see Conn for documentation. | |
92 | |
93 // Read implements the Conn Read method. | |
94 func (c *plan9Conn) Read(b []byte) (n int, err error) { | |
95 if !c.ok() { | |
96 return 0, syscall.EINVAL | |
97 } | |
98 if c.data == nil { | |
99 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) | |
100 if err != nil { | |
101 return 0, err | |
102 } | |
103 } | |
104 n, err = c.data.Read(b) | |
105 if c.proto == "udp" && err == io.EOF { | |
106 n = 0 | |
107 err = nil | |
108 } | |
109 return | |
110 } | |
111 | |
112 // Write implements the Conn Write method. | |
113 func (c *plan9Conn) Write(b []byte) (n int, err error) { | |
114 if !c.ok() { | |
115 return 0, syscall.EINVAL | |
116 } | |
117 if c.data == nil { | |
118 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) | |
119 if err != nil { | |
120 return 0, err | |
121 } | |
122 } | |
123 return c.data.Write(b) | |
124 } | |
125 | |
126 // Close closes the connection. | |
127 func (c *plan9Conn) Close() error { | |
128 if !c.ok() { | |
129 return syscall.EINVAL | |
130 } | |
131 err := c.ctl.Close() | |
132 if err != nil { | |
133 return err | |
134 } | |
135 if c.data != nil { | |
136 err = c.data.Close() | |
137 } | |
138 c.ctl = nil | |
139 c.data = nil | |
140 return err | |
141 } | |
142 | |
143 // LocalAddr returns the local network address. | |
144 func (c *plan9Conn) LocalAddr() Addr { | |
145 if !c.ok() { | |
146 return nil | |
147 } | |
148 return c.laddr | |
149 } | |
150 | |
151 // RemoteAddr returns the remote network address. | |
152 func (c *plan9Conn) RemoteAddr() Addr { | |
153 if !c.ok() { | |
154 return nil | |
155 } | |
156 return c.raddr | |
157 } | |
158 | |
159 // SetDeadline implements the Conn SetDeadline method. | |
160 func (c *plan9Conn) SetDeadline(t time.Time) error { | |
161 return syscall.EPLAN9 | |
162 } | |
163 | |
164 // SetReadDeadline implements the Conn SetReadDeadline method. | |
165 func (c *plan9Conn) SetReadDeadline(t time.Time) error { | |
166 return syscall.EPLAN9 | |
167 } | |
168 | |
169 // SetWriteDeadline implements the Conn SetWriteDeadline method. | |
170 func (c *plan9Conn) SetWriteDeadline(t time.Time) error { | |
171 return syscall.EPLAN9 | |
172 } | |
173 | |
174 // SetReadBuffer sets the size of the operating system's receive | |
175 // buffer associated with the connection. | |
176 func (c *plan9Conn) SetReadBuffer(bytes int) error { | |
177 return syscall.EPLAN9 | |
178 } | |
179 | |
180 // SetWriteBuffer sets the size of the operating system's transmit | |
181 // buffer associated with the connection. | |
182 func (c *plan9Conn) SetWriteBuffer(bytes int) error { | |
183 return syscall.EPLAN9 | |
184 } | |
185 | |
186 // File returns a copy of the underlying os.File, set to blocking | |
187 // mode. It is the caller's responsibility to close f when finished. | |
188 // Closing c does not affect f, and closing f does not affect c. | |
189 func (c *plan9Conn) File() (f *os.File, err error) { | |
190 return nil, syscall.EPLAN9 | |
191 } | |
192 | |
193 func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string,
err error) { | 71 func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string,
err error) { |
194 var ( | 72 var ( |
195 ip IP | 73 ip IP |
196 port int | 74 port int |
197 ) | 75 ) |
198 switch a := addr.(type) { | 76 switch a := addr.(type) { |
199 case *TCPAddr: | 77 case *TCPAddr: |
200 proto = "tcp" | 78 proto = "tcp" |
201 ip = a.IP | 79 ip = a.IP |
202 port = a.Port | 80 port = a.Port |
(...skipping 16 matching lines...) Expand all Loading... |
219 } | 97 } |
220 var buf [16]byte | 98 var buf [16]byte |
221 n, err := f.Read(buf[:]) | 99 n, err := f.Read(buf[:]) |
222 if err != nil { | 100 if err != nil { |
223 f.Close() | 101 f.Close() |
224 return | 102 return |
225 } | 103 } |
226 return f, dest, proto, string(buf[:n]), nil | 104 return f, dest, proto, string(buf[:n]), nil |
227 } | 105 } |
228 | 106 |
229 func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) { | 107 func dialPlan9(net string, laddr, raddr Addr) (*netFD, error) { |
230 f, dest, proto, name, err := startPlan9(net, raddr) | 108 f, dest, proto, name, err := startPlan9(net, raddr) |
231 if err != nil { | 109 if err != nil { |
232 » » return | 110 » » return nil, err |
233 } | 111 } |
234 _, err = f.WriteString("connect " + dest) | 112 _, err = f.WriteString("connect " + dest) |
235 if err != nil { | 113 if err != nil { |
236 f.Close() | 114 f.Close() |
237 » » return | 115 » » return nil, err |
238 } | 116 } |
239 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") | 117 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") |
240 if err != nil { | 118 if err != nil { |
241 f.Close() | 119 f.Close() |
242 » » return | 120 » » return nil, err |
243 } | 121 } |
244 raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote") | 122 raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote") |
245 if err != nil { | 123 if err != nil { |
246 f.Close() | 124 f.Close() |
247 » » return | 125 » » return nil, err |
248 } | 126 } |
249 » return newPlan9Conn(proto, name, f, laddr, raddr), nil | 127 » return newFD(proto, name, f, laddr, raddr), nil |
250 } | 128 } |
251 | 129 |
252 type plan9Listener struct { | 130 func listenPlan9(net string, laddr Addr) (*netFD, error) { |
253 » proto, name, dir string | |
254 » ctl *os.File | |
255 » laddr Addr | |
256 } | |
257 | |
258 func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) { | |
259 f, dest, proto, name, err := startPlan9(net, laddr) | 131 f, dest, proto, name, err := startPlan9(net, laddr) |
260 if err != nil { | 132 if err != nil { |
261 » » return | 133 » » return nil, err |
262 } | 134 } |
263 _, err = f.WriteString("announce " + dest) | 135 _, err = f.WriteString("announce " + dest) |
264 if err != nil { | 136 if err != nil { |
265 f.Close() | 137 f.Close() |
266 » » return | 138 » » return nil, err |
267 } | 139 } |
268 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") | 140 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") |
269 if err != nil { | 141 if err != nil { |
270 f.Close() | 142 f.Close() |
271 » » return | 143 » » return nil, err |
272 } | 144 } |
273 » l = new(plan9Listener) | 145 » return &netFD{proto: proto, name: name, dir: "/net/" + proto + "/" + nam
e, ctl: f, laddr: laddr}, nil |
274 » l.proto = proto | |
275 » l.name = name | |
276 » l.dir = "/net/" + proto + "/" + name | |
277 » l.ctl = f | |
278 » l.laddr = laddr | |
279 » return l, nil | |
280 } | 146 } |
281 | 147 |
282 func (l *plan9Listener) plan9Conn() *plan9Conn { | 148 func (l *netFD) netFD() *netFD { |
283 » return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil) | 149 » return newFD(l.proto, l.name, l.ctl, l.laddr, nil) |
284 } | 150 } |
285 | 151 |
286 func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) { | 152 func (l *netFD) acceptPlan9() (*netFD, error) { |
287 f, err := os.Open(l.dir + "/listen") | 153 f, err := os.Open(l.dir + "/listen") |
288 if err != nil { | 154 if err != nil { |
289 » » return | 155 » » return nil, err |
290 } | 156 } |
291 var buf [16]byte | 157 var buf [16]byte |
292 n, err := f.Read(buf[:]) | 158 n, err := f.Read(buf[:]) |
293 if err != nil { | 159 if err != nil { |
294 f.Close() | 160 f.Close() |
295 » » return | 161 » » return nil, err |
296 } | 162 } |
297 name := string(buf[:n]) | 163 name := string(buf[:n]) |
298 laddr, err := readPlan9Addr(l.proto, l.dir+"/local") | 164 laddr, err := readPlan9Addr(l.proto, l.dir+"/local") |
299 if err != nil { | 165 if err != nil { |
300 f.Close() | 166 f.Close() |
301 » » return | 167 » » return nil, err |
302 } | 168 } |
303 raddr, err := readPlan9Addr(l.proto, l.dir+"/remote") | 169 raddr, err := readPlan9Addr(l.proto, l.dir+"/remote") |
304 if err != nil { | 170 if err != nil { |
305 f.Close() | 171 f.Close() |
306 » » return | 172 » » return nil, err |
307 } | 173 } |
308 » return newPlan9Conn(l.proto, name, f, laddr, raddr), nil | 174 » return newFD(l.proto, name, f, laddr, raddr), nil |
309 } | 175 } |
310 | |
311 func (l *plan9Listener) Accept() (c Conn, err error) { | |
312 c1, err := l.acceptPlan9() | |
313 if err != nil { | |
314 return | |
315 } | |
316 return c1, nil | |
317 } | |
318 | |
319 func (l *plan9Listener) Close() error { | |
320 if l == nil || l.ctl == nil { | |
321 return syscall.EINVAL | |
322 } | |
323 return l.ctl.Close() | |
324 } | |
325 | |
326 func (l *plan9Listener) Addr() Addr { return l.laddr } | |
327 | |
328 // SetDeadline sets the deadline associated with the listener. | |
329 // A zero time value disables the deadline. | |
330 func (l *plan9Listener) SetDeadline(t time.Time) error { | |
331 return syscall.EPLAN9 | |
332 } | |
333 | |
334 // File returns a copy of the underlying os.File, set to blocking | |
335 // mode. It is the caller's responsibility to close f when finished. | |
336 // Closing l does not affect f, and closing f does not affect l. | |
337 func (l *plan9Listener) File() (f *os.File, err error) { | |
338 return nil, syscall.EPLAN9 | |
339 } | |
OLD | NEW |