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.
14 // Network file descritor.
16 // locking/lifetime of sysfd + serialize access to Read and Write methods
19 // immutable until Close
28 netdir
string // default network
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
)
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
45 func (fd
*netFD
) init() error
{
46 // stub for future fd.pd.Init(fd)
50 func (fd
*netFD
) name() string {
53 ls
= fd
.laddr
.String()
56 rs
= fd
.raddr
.String()
58 return fd
.proto
+ ":" + ls
+ "->" + rs
61 func (fd
*netFD
) ok() bool { return fd
!= nil && fd
.ctl
!= nil }
63 func (fd
*netFD
) destroy() {
69 if err1
:= fd
.data
.Close(); err1
!= nil && err
== nil {
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() {
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() {
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) {
103 // Unlock for reading and remove a reference to this FD.
104 func (fd
*netFD
) readUnlock() {
105 if fd
.fdmu
.RWUnlock(true) {
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) {
119 // Unlock for writing and remove a reference to this FD.
120 func (fd
*netFD
) writeUnlock() {
121 if fd
.fdmu
.RWUnlock(false) {
126 func (fd
*netFD
) Read(b
[]byte) (n
int, err error
) {
127 if !fd
.ok() || fd
.data
== nil {
128 return 0, syscall
.EINVAL
130 if err
:= fd
.readLock(); err
!= nil {
133 defer fd
.readUnlock()
134 n
, err
= fd
.data
.Read(b
)
135 if fd
.proto
== "udp" && err
== io
.EOF
{
142 func (fd
*netFD
) Write(b
[]byte) (n
int, err error
) {
143 if !fd
.ok() || fd
.data
== nil {
144 return 0, syscall
.EINVAL
146 if err
:= fd
.writeLock(); err
!= nil {
149 defer fd
.writeUnlock()
150 return fd
.data
.Write(b
)
153 func (fd
*netFD
) closeRead() error
{
155 return syscall
.EINVAL
157 return syscall
.EPLAN9
160 func (fd
*netFD
) closeWrite() error
{
162 return syscall
.EINVAL
164 return syscall
.EPLAN9
167 func (fd
*netFD
) Close() error
{
168 if !fd
.fdmu
.IncrefAndClose() {
172 return syscall
.EINVAL
174 err
:= fd
.ctl
.Close()
176 if err1
:= fd
.data
.Close(); err1
!= nil && err
== nil {
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
190 return fd
.file(fd
.data
, fd
.dir
+"/data")
193 func (l
*TCPListener
) dup() (*os
.File
, error
) {
195 return nil, syscall
.EINVAL
197 return l
.fd
.file(l
.fd
.ctl
, l
.fd
.dir
+"/ctl")
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()
205 return nil, &OpError
{"dup", s
, fd
.laddr
, err
}
207 return os
.NewFile(uintptr(dfd
), s
), nil
210 func (fd
*netFD
) setDeadline(t time
.Time
) error
{
211 return syscall
.EPLAN9
214 func (fd
*netFD
) setReadDeadline(t time
.Time
) error
{
215 return syscall
.EPLAN9
218 func (fd
*netFD
) setWriteDeadline(t time
.Time
) error
{
219 return syscall
.EPLAN9
222 func setReadBuffer(fd
*netFD
, bytes
int) error
{
223 return syscall
.EPLAN9
226 func setWriteBuffer(fd
*netFD
, bytes
int) error
{
227 return syscall
.EPLAN9
230 func skipRawSocketTests() (skip
bool, skipmsg
string, err error
) {
231 return true, "skipping test on plan9", nil