111
|
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"
|
131
|
12 "time"
|
111
|
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 }
|
131
|
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 }
|