github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/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 "internal/poll" 9 "io" 10 "os" 11 "syscall" 12 "time" 13 ) 14 15 // Network file descriptor. 16 type netFD struct { 17 pfd poll.FD 18 19 // immutable until Close 20 net string 21 n string 22 dir string 23 listen, ctl, data *os.File 24 laddr, raddr Addr 25 isStream bool 26 } 27 28 var netdir = "/net" // default network 29 30 func newFD(net, name string, listen, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) { 31 ret := &netFD{ 32 net: net, 33 n: name, 34 dir: netdir + "/" + net + "/" + name, 35 listen: listen, 36 ctl: ctl, data: data, 37 laddr: laddr, 38 raddr: raddr, 39 } 40 ret.pfd.Destroy = ret.destroy 41 return ret, nil 42 } 43 44 func (fd *netFD) init() error { 45 // stub for future fd.pd.Init(fd) 46 return nil 47 } 48 49 func (fd *netFD) name() string { 50 var ls, rs string 51 if fd.laddr != nil { 52 ls = fd.laddr.String() 53 } 54 if fd.raddr != nil { 55 rs = fd.raddr.String() 56 } 57 return fd.net + ":" + ls + "->" + rs 58 } 59 60 func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil } 61 62 func (fd *netFD) destroy() { 63 if !fd.ok() { 64 return 65 } 66 err := fd.ctl.Close() 67 if fd.data != nil { 68 if err1 := fd.data.Close(); err1 != nil && err == nil { 69 err = err1 70 } 71 } 72 if fd.listen != nil { 73 if err1 := fd.listen.Close(); err1 != nil && err == nil { 74 err = err1 75 } 76 } 77 fd.ctl = nil 78 fd.data = nil 79 fd.listen = nil 80 } 81 82 func (fd *netFD) Read(b []byte) (n int, err error) { 83 if !fd.ok() || fd.data == nil { 84 return 0, syscall.EINVAL 85 } 86 n, err = fd.pfd.Read(fd.data.Read, b) 87 if fd.net == "udp" && err == io.EOF { 88 n = 0 89 err = nil 90 } 91 return 92 } 93 94 func (fd *netFD) Write(b []byte) (n int, err error) { 95 if !fd.ok() || fd.data == nil { 96 return 0, syscall.EINVAL 97 } 98 return fd.pfd.Write(fd.data.Write, b) 99 } 100 101 func (fd *netFD) closeRead() error { 102 if !fd.ok() { 103 return syscall.EINVAL 104 } 105 return syscall.EPLAN9 106 } 107 108 func (fd *netFD) closeWrite() error { 109 if !fd.ok() { 110 return syscall.EINVAL 111 } 112 return syscall.EPLAN9 113 } 114 115 func (fd *netFD) Close() error { 116 if err := fd.pfd.Close(); err != nil { 117 return err 118 } 119 if !fd.ok() { 120 return syscall.EINVAL 121 } 122 if fd.net == "tcp" { 123 // The following line is required to unblock Reads. 124 _, err := fd.ctl.WriteString("close") 125 if err != nil { 126 return err 127 } 128 } 129 err := fd.ctl.Close() 130 if fd.data != nil { 131 if err1 := fd.data.Close(); err1 != nil && err == nil { 132 err = err1 133 } 134 } 135 if fd.listen != nil { 136 if err1 := fd.listen.Close(); err1 != nil && err == nil { 137 err = err1 138 } 139 } 140 fd.ctl = nil 141 fd.data = nil 142 fd.listen = nil 143 return err 144 } 145 146 // This method is only called via Conn. 147 func (fd *netFD) dup() (*os.File, error) { 148 if !fd.ok() || fd.data == nil { 149 return nil, syscall.EINVAL 150 } 151 return fd.file(fd.data, fd.dir+"/data") 152 } 153 154 func (l *TCPListener) dup() (*os.File, error) { 155 if !l.fd.ok() { 156 return nil, syscall.EINVAL 157 } 158 return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl") 159 } 160 161 func (fd *netFD) file(f *os.File, s string) (*os.File, error) { 162 dfd, err := syscall.Dup(int(f.Fd()), -1) 163 if err != nil { 164 return nil, os.NewSyscallError("dup", err) 165 } 166 return os.NewFile(uintptr(dfd), s), nil 167 } 168 169 func setReadBuffer(fd *netFD, bytes int) error { 170 return syscall.EPLAN9 171 } 172 173 func setWriteBuffer(fd *netFD, bytes int) error { 174 return syscall.EPLAN9 175 } 176 177 func (fd *netFD) SetDeadline(t time.Time) error { 178 return fd.pfd.SetDeadline(t) 179 } 180 181 func (fd *netFD) SetReadDeadline(t time.Time) error { 182 return fd.pfd.SetReadDeadline(t) 183 } 184 185 func (fd *netFD) SetWriteDeadline(t time.Time) error { 186 return fd.pfd.SetWriteDeadline(t) 187 }