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.
5 // IP sockets stubs for Plan 9
17 // /sys/include/ape/sys/socket.h:/SOMAXCONN
18 var listenerBacklog = 5
20 // probeIPv6Stack returns two boolean values. If the first boolean
21 // value is true, kernel supports basic IPv6 functionality. If the
22 // second boolean value is true, kernel supports IPv6 IPv4-mapping.
23 func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
27 // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
28 func parsePlan9Addr(s string) (ip IP, iport int, err error) {
29 addr := IPv4zero // address contains port only
30 i := byteIndex(s, '!')
34 return nil, 0, errors.New("net: parsing IP failed")
37 p, _, ok := dtoi(s[i+1:], 0)
39 return nil, 0, errors.New("net: parsing port failed")
41 if p < 0 || p > 0xFFFF {
42 return nil, 0, &AddrError{"invalid port", string(p)}
47 func readPlan9Addr(proto, filename string) (addr Addr, err error) {
50 f, err := os.Open(filename)
55 n, err := f.Read(buf[:])
59 ip, port, err := parsePlan9Addr(string(buf[:n]))
65 addr = &TCPAddr{ip, port}
67 addr = &UDPAddr{ip, port}
69 return nil, errors.New("unknown protocol " + proto)
74 type plan9Conn struct {
75 proto, name, dir string
80 func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Conn {
81 return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, laddr, raddr}
84 func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil }
86 // Implementation of the Conn interface - see Conn for documentation.
88 // Read implements the Conn Read method.
89 func (c *plan9Conn) Read(b []byte) (n int, err error) {
91 return 0, syscall.EINVAL
94 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
99 n, err = c.data.Read(b)
100 if c.proto == "udp" && err == io.EOF {
107 // Write implements the Conn Write method.
108 func (c *plan9Conn) Write(b []byte) (n int, err error) {
110 return 0, syscall.EINVAL
113 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
118 return c.data.Write(b)
121 // Close closes the connection.
122 func (c *plan9Conn) Close() error {
124 return syscall.EINVAL
138 // LocalAddr returns the local network address.
139 func (c *plan9Conn) LocalAddr() Addr {
146 // RemoteAddr returns the remote network address.
147 func (c *plan9Conn) RemoteAddr() Addr {
154 // SetDeadline implements the Conn SetDeadline method.
155 func (c *plan9Conn) SetDeadline(t time.Time) error {
156 return syscall.EPLAN9
159 // SetReadDeadline implements the Conn SetReadDeadline method.
160 func (c *plan9Conn) SetReadDeadline(t time.Time) error {
161 return syscall.EPLAN9
164 // SetWriteDeadline implements the Conn SetWriteDeadline method.
165 func (c *plan9Conn) SetWriteDeadline(t time.Time) error {
166 return syscall.EPLAN9
169 // SetReadBuffer sets the size of the operating system's receive
170 // buffer associated with the connection.
171 func (c *plan9Conn) SetReadBuffer(bytes int) error {
172 return syscall.EPLAN9
175 // SetWriteBuffer sets the size of the operating system's transmit
176 // buffer associated with the connection.
177 func (c *plan9Conn) SetWriteBuffer(bytes int) error {
178 return syscall.EPLAN9
181 // File returns a copy of the underlying os.File, set to blocking
182 // mode. It is the caller's responsibility to close f when finished.
183 // Closing c does not affect f, and closing f does not affect c.
184 func (c *plan9Conn) File() (f *os.File, err error) {
185 return nil, syscall.EPLAN9
188 func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
193 switch a := addr.(type) {
203 err = UnknownNetworkError(net)
207 clone, dest, err := queryCS1(proto, ip, port)
211 f, err := os.OpenFile(clone, os.O_RDWR, 0)
216 n, err := f.Read(buf[:])
221 return f, dest, proto, string(buf[:n]), nil
224 func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) {
225 f, dest, proto, name, err := startPlan9(net, raddr)
229 _, err = f.WriteString("connect " + dest)
234 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
239 raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote")
244 return newPlan9Conn(proto, name, f, laddr, raddr), nil
247 type plan9Listener struct {
248 proto, name, dir string
253 func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) {
254 f, dest, proto, name, err := startPlan9(net, laddr)
258 _, err = f.WriteString("announce " + dest)
263 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
268 l = new(plan9Listener)
271 l.dir = "/net/" + proto + "/" + name
277 func (l *plan9Listener) plan9Conn() *plan9Conn {
278 return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil)
281 func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) {
282 f, err := os.Open(l.dir + "/listen")
287 n, err := f.Read(buf[:])
292 name := string(buf[:n])
293 laddr, err := readPlan9Addr(l.proto, l.dir+"/local")
298 raddr, err := readPlan9Addr(l.proto, l.dir+"/remote")
303 return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
306 func (l *plan9Listener) Accept() (c Conn, err error) {
307 c1, err := l.acceptPlan9()
314 func (l *plan9Listener) Close() error {
315 if l == nil || l.ctl == nil {
316 return syscall.EINVAL
321 func (l *plan9Listener) Addr() Addr { return l.laddr }
323 // SetDeadline sets the deadline associated with the listener.
324 // A zero time value disables the deadline.
325 func (l *plan9Listener) SetDeadline(t time.Time) error {
326 return syscall.EPLAN9
329 // File returns a copy of the underlying os.File, set to blocking
330 // mode. It is the caller's responsibility to close f when finished.
331 // Closing l does not affect f, and closing f does not affect l.
332 func (l *plan9Listener) File() (f *os.File, err error) {
333 return nil, syscall.EPLAN9