aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Rarick <kr@xph.us>2010-11-05 14:02:03 -0400
committerRuss Cox <rsc@golang.org>2010-11-05 14:02:03 -0400
commita144e3ec36f48ac67b74daccb456a3a90cd04134 (patch)
tree4ba4890918e32822f8930991926b790458d9bcee
parent5df5d3276d11e01b07d092609f1d8c5f1dfed598 (diff)
downloadgo-a144e3ec36f48ac67b74daccb456a3a90cd04134.tar.gz
go-a144e3ec36f48ac67b74daccb456a3a90cd04134.zip
net: provide public access to file descriptors
Fixes #918. R=rsc, rog, brainman CC=golang-dev https://golang.org/cl/2904041
-rw-r--r--src/pkg/net/fd.go14
-rw-r--r--src/pkg/net/fd_windows.go5
-rw-r--r--src/pkg/net/tcpsock.go10
-rw-r--r--src/pkg/net/udpsock.go5
-rw-r--r--src/pkg/net/unixsock.go10
5 files changed, 44 insertions, 0 deletions
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 7d3f227c1c..d300e4bda5 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -517,3 +517,17 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
}
return nfd, nil
}
+
+func (fd *netFD) dup() (f *os.File, err os.Error) {
+ ns, e := syscall.Dup(fd.sysfd)
+ if e != 0 {
+ return nil, &OpError{"dup", fd.net, fd.laddr, os.Errno(e)}
+ }
+
+ // We want blocking mode for the new fd, hence the double negative.
+ if e = syscall.SetNonblock(ns, false); e != 0 {
+ return nil, &OpError{"setnonblock", fd.net, fd.laddr, os.Errno(e)}
+ }
+
+ return os.NewFile(ns, fd.sysfile.Name()), nil
+}
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index c3ed9639d2..1da2ca47ff 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -373,3 +373,8 @@ func init() {
initErr = os.NewSyscallError("WSAStartup", e)
}
}
+
+func (fd *netFD) dup() (f *os.File, err os.Error) {
+ // TODO: Implement this
+ return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index eb846694ba..b0cb8f9992 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -208,6 +208,11 @@ func (c *TCPConn) SetNoDelay(noDelay bool) os.Error {
return setNoDelay(c.fd, noDelay)
}
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *TCPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
+
// DialTCP is like Dial but can only connect to TCP networks
// and returns a TCPConn structure.
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) {
@@ -281,3 +286,8 @@ func (l *TCPListener) Close() os.Error {
// Addr returns the listener's network address, a *TCPAddr.
func (l *TCPListener) Addr() Addr { return l.fd.laddr }
+
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (l *TCPListener) File() (f *os.File, err os.Error) { return l.fd.dup() }
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 89a074755b..0270954c17 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -274,3 +274,8 @@ func (c *UDPConn) BindToDevice(device string) os.Error {
defer c.fd.decref()
return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
}
+
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index 93535130a2..82c0b6d05b 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -277,6 +277,11 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
return c.WriteToUnix(b, a)
}
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *UnixConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
+
// DialUnix connects to the remote address raddr on the network net,
// which must be "unix" or "unixgram". If laddr is not nil, it is used
// as the local address for the connection.
@@ -369,6 +374,11 @@ func (l *UnixListener) Close() os.Error {
// Addr returns the listener's network address.
func (l *UnixListener) Addr() Addr { return l.fd.laddr }
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (l *UnixListener) File() (f *os.File, err os.Error) { return l.fd.dup() }
+
// ListenUnixgram listens for incoming Unix datagram packets addressed to the
// local address laddr. The returned connection c's ReadFrom
// and WriteTo methods can be used to receive and send UDP