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
5package net
6
7import (
8	"internal/poll"
9	"io"
10	"os"
11	"syscall"
12	"time"
13)
14
15// Network file descriptor.
16type 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
28var netdir = "/net" // default network
29
30func 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
44func (fd *netFD) init() error {
45	// stub for future fd.pd.Init(fd)
46	return nil
47}
48
49func (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
60func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
61
62func (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
82func (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
94func (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
101func (fd *netFD) closeRead() error {
102	if !fd.ok() {
103		return syscall.EINVAL
104	}
105	return syscall.EPLAN9
106}
107
108func (fd *netFD) closeWrite() error {
109	if !fd.ok() {
110		return syscall.EINVAL
111	}
112	return syscall.EPLAN9
113}
114
115func (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.
147func (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
154func (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
161func (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
169func setReadBuffer(fd *netFD, bytes int) error {
170	return syscall.EPLAN9
171}
172
173func setWriteBuffer(fd *netFD, bytes int) error {
174	return syscall.EPLAN9
175}
176
177func (fd *netFD) SetDeadline(t time.Time) error {
178	return fd.pfd.SetDeadline(t)
179}
180
181func (fd *netFD) SetReadDeadline(t time.Time) error {
182	return fd.pfd.SetReadDeadline(t)
183}
184
185func (fd *netFD) SetWriteDeadline(t time.Time) error {
186	return fd.pfd.SetWriteDeadline(t)
187}
188