github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/net/fd_plan9.go (about) 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. 4 5 package net 6 7 import ( 8 "io" 9 "os" 10 "syscall" 11 "time" 12 ) 13 14 // Network file descritor. 15 type netFD struct { 16 // locking/lifetime of sysfd + serialize access to Read and Write methods 17 fdmu fdMutex 18 19 // immutable until Close 20 proto string 21 n string 22 dir string 23 ctl, data *os.File 24 laddr, raddr Addr 25 } 26 27 var ( 28 netdir string // default network 29 ) 30 31 func sysInit() { 32 netdir = "/net" 33 } 34 35 func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) { 36 // On plan9, use the relatively inefficient 37 // goroutine-racing implementation. 38 return dialChannel(net, ra, dialer, deadline) 39 } 40 41 func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) { 42 return &netFD{proto: proto, n: name, dir: netdir + "/" + proto + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil 43 } 44 45 func (fd *netFD) init() error { 46 // stub for future fd.pd.Init(fd) 47 return nil 48 } 49 50 func (fd *netFD) name() string { 51 var ls, rs string 52 if fd.laddr != nil { 53 ls = fd.laddr.String() 54 } 55 if fd.raddr != nil { 56 rs = fd.raddr.String() 57 } 58 return fd.proto + ":" + ls + "->" + rs 59 } 60 61 func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil } 62 63 func (fd *netFD) destroy() { 64 if !fd.ok() { 65 return 66 } 67 err := fd.ctl.Close() 68 if fd.data != nil { 69 if err1 := fd.data.Close(); err1 != nil && err == nil { 70 err = err1 71 } 72 } 73 fd.ctl = nil 74 fd.data = nil 75 } 76 77 // Add a reference to this fd. 78 // Returns an error if the fd cannot be used. 79 func (fd *netFD) incref() error { 80 if !fd.fdmu.Incref() { 81 return errClosing 82 } 83 return nil 84 } 85 86 // Remove a reference to this FD and close if we've been asked to do so 87 // (and there are no references left). 88 func (fd *netFD) decref() { 89 if fd.fdmu.Decref() { 90 fd.destroy() 91 } 92 } 93 94 // Add a reference to this fd and lock for reading. 95 // Returns an error if the fd cannot be used. 96 func (fd *netFD) readLock() error { 97 if !fd.fdmu.RWLock(true) { 98 return errClosing 99 } 100 return nil 101 } 102 103 // Unlock for reading and remove a reference to this FD. 104 func (fd *netFD) readUnlock() { 105 if fd.fdmu.RWUnlock(true) { 106 fd.destroy() 107 } 108 } 109 110 // Add a reference to this fd and lock for writing. 111 // Returns an error if the fd cannot be used. 112 func (fd *netFD) writeLock() error { 113 if !fd.fdmu.RWLock(false) { 114 return errClosing 115 } 116 return nil 117 } 118 119 // Unlock for writing and remove a reference to this FD. 120 func (fd *netFD) writeUnlock() { 121 if fd.fdmu.RWUnlock(false) { 122 fd.destroy() 123 } 124 } 125 126 func (fd *netFD) Read(b []byte) (n int, err error) { 127 if !fd.ok() || fd.data == nil { 128 return 0, syscall.EINVAL 129 } 130 if err := fd.readLock(); err != nil { 131 return 0, err 132 } 133 defer fd.readUnlock() 134 n, err = fd.data.Read(b) 135 if fd.proto == "udp" && err == io.EOF { 136 n = 0 137 err = nil 138 } 139 return 140 } 141 142 func (fd *netFD) Write(b []byte) (n int, err error) { 143 if !fd.ok() || fd.data == nil { 144 return 0, syscall.EINVAL 145 } 146 if err := fd.writeLock(); err != nil { 147 return 0, err 148 } 149 defer fd.writeUnlock() 150 return fd.data.Write(b) 151 } 152 153 func (fd *netFD) closeRead() error { 154 if !fd.ok() { 155 return syscall.EINVAL 156 } 157 return syscall.EPLAN9 158 } 159 160 func (fd *netFD) closeWrite() error { 161 if !fd.ok() { 162 return syscall.EINVAL 163 } 164 return syscall.EPLAN9 165 } 166 167 func (fd *netFD) Close() error { 168 if !fd.fdmu.IncrefAndClose() { 169 return errClosing 170 } 171 if !fd.ok() { 172 return syscall.EINVAL 173 } 174 err := fd.ctl.Close() 175 if fd.data != nil { 176 if err1 := fd.data.Close(); err1 != nil && err == nil { 177 err = err1 178 } 179 } 180 fd.ctl = nil 181 fd.data = nil 182 return err 183 } 184 185 // This method is only called via Conn. 186 func (fd *netFD) dup() (*os.File, error) { 187 if !fd.ok() || fd.data == nil { 188 return nil, syscall.EINVAL 189 } 190 return fd.file(fd.data, fd.dir+"/data") 191 } 192 193 func (l *TCPListener) dup() (*os.File, error) { 194 if !l.fd.ok() { 195 return nil, syscall.EINVAL 196 } 197 return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl") 198 } 199 200 func (fd *netFD) file(f *os.File, s string) (*os.File, error) { 201 syscall.ForkLock.RLock() 202 dfd, err := syscall.Dup(int(f.Fd()), -1) 203 syscall.ForkLock.RUnlock() 204 if err != nil { 205 return nil, &OpError{"dup", s, fd.laddr, err} 206 } 207 return os.NewFile(uintptr(dfd), s), nil 208 } 209 210 func (fd *netFD) setDeadline(t time.Time) error { 211 return syscall.EPLAN9 212 } 213 214 func (fd *netFD) setReadDeadline(t time.Time) error { 215 return syscall.EPLAN9 216 } 217 218 func (fd *netFD) setWriteDeadline(t time.Time) error { 219 return syscall.EPLAN9 220 } 221 222 func setReadBuffer(fd *netFD, bytes int) error { 223 return syscall.EPLAN9 224 } 225 226 func setWriteBuffer(fd *netFD, bytes int) error { 227 return syscall.EPLAN9 228 } 229 230 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 231 return true, "skipping test on plan9", nil 232 }