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