Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1657)

Unified Diff: src/net/file_windows.go

Issue 177590043: code review 177590043: net: FileListener on windows
Patch Set: diff -r ffe33f1f1f17bf7d9bd14d8a8931dc905a75d011 http://go.googlecode.com/hg/ Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/net/file_test.go ('k') | src/syscall/syscall_windows.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/net/file_windows.go
===================================================================
--- a/src/net/file_windows.go
+++ b/src/net/file_windows.go
@@ -9,13 +9,106 @@
"syscall"
)
+func dupCloseOnExec(fd int) (syscall.Handle, error) {
+ var h syscall.Handle
+ p, _ := syscall.GetCurrentProcess()
+ err := syscall.DuplicateHandle(p, syscall.Handle(fd), p, &h, 0, false, syscall.DUPLICATE_SAME_ACCESS)
+ if err != nil {
+ return 0, err
+ }
+ return h, nil
+}
+
+func newFileFD(f *os.File) (*netFD, error) {
+ fd, err := dupCloseOnExec(int(f.Fd()))
+ if err != nil {
+ return nil, os.NewSyscallError("dup", err)
+ }
+
+ if err = syscall.SetNonblock(fd, true); err != nil {
+ closesocket(fd)
+ return nil, err
+ }
+
+ sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
+ if err != nil {
+ closesocket(fd)
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ lsa, err := syscall.Getsockname(fd)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockname", err)
+ }
+
+ family := syscall.AF_UNSPEC
+ toAddr := sockaddrToTCP
+ switch lsa.(type) {
+ default:
+ closesocket(fd)
+ return nil, syscall.EINVAL
+ case *syscall.SockaddrInet4:
+ family = syscall.AF_INET
+ if sotype == syscall.SOCK_DGRAM {
+ toAddr = sockaddrToUDP
+ } else if sotype == syscall.SOCK_RAW {
+ toAddr = sockaddrToIP
+ }
+ case *syscall.SockaddrInet6:
+ family = syscall.AF_INET6
+ if sotype == syscall.SOCK_DGRAM {
+ toAddr = sockaddrToUDP
+ } else if sotype == syscall.SOCK_RAW {
+ toAddr = sockaddrToIP
+ }
+ case *syscall.SockaddrUnix:
+ return nil, os.NewSyscallError("UnixListener", syscall.EWINDOWS)
+ }
+ laddr := toAddr(lsa)
+ rsa, _ := syscall.Getpeername(fd)
+ raddr := toAddr(rsa)
+
+ netfd, err := newFD(fd, family, sotype, laddr.Network())
+ if err != nil {
+ closesocket(fd)
+ return nil, err
+ }
+ // fd is not handled yet
+ if err := netfd.init(); err != nil {
+ // handle invalid parameter. When passing same handle to
+ // CreateIoCompletionPort twice, it returns ERROR_INVALID_PARAMETER(87).
+ // Ignoring this here because when passing handle into this function
+ // from external process, Or create socket manually and pass to here,
+ // this init() should work gracefully.
+ if errno, ok := err.(syscall.Errno); ok && int(errno) != -87 {
+ netfd.Close()
+ return nil, err
+ }
+ }
+ netfd.setAddr(laddr, raddr)
+ return netfd, nil
+}
+
// FileConn returns a copy of the network connection corresponding to
// the open file f. 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 FileConn(f *os.File) (c Conn, err error) {
- // TODO: Implement this
- return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
+ fd, err := newFileFD(f)
+ if err != nil {
+ return nil, err
+ }
+ switch fd.laddr.(type) {
+ case *TCPAddr:
+ return newTCPConn(fd), nil
+ case *UDPAddr:
+ return newUDPConn(fd), nil
+ case *IPAddr:
+ return newIPConn(fd), nil
+ case *UnixAddr:
+ return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
+ }
+ fd.Close()
+ return nil, syscall.EINVAL
}
// FileListener returns a copy of the network listener corresponding
@@ -23,8 +116,18 @@
// when finished. Closing l does not affect f, and closing f does not
// affect l.
func FileListener(f *os.File) (l Listener, err error) {
- // TODO: Implement this
- return nil, os.NewSyscallError("FileListener", syscall.EWINDOWS)
+ fd, err := newFileFD(f)
+ if err != nil {
+ return nil, err
+ }
+ switch fd.laddr.(type) {
+ case *TCPAddr:
+ return &TCPListener{fd}, nil
+ case *UnixAddr:
+ return nil, os.NewSyscallError("UnixListener", syscall.EWINDOWS)
+ }
+ fd.Close()
+ return nil, syscall.EINVAL
}
// FilePacketConn returns a copy of the packet network connection
« no previous file with comments | « src/net/file_test.go ('k') | src/syscall/syscall_windows.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b