1 // Copyright 2010 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 // BUG(brainman): The Windows implementation does not implement SetTimeout.
16 // IO completion result parameters.
17 type ioResult struct {
23 // Network file descriptor.
25 // locking/lifetime of sysfd
30 // immutable until Close
50 type InvalidConnError struct{}
52 func (e *InvalidConnError) String() string { return "invalid net.Conn" }
53 func (e *InvalidConnError) Temporary() bool { return false }
54 func (e *InvalidConnError) Timeout() bool { return false }
56 // pollServer will run around waiting for io completion request
57 // to arrive. Every request received will contain channel to signal
58 // io owner about the completion.
60 type pollServer struct {
64 func newPollServer() (s *pollServer, err os.Error) {
67 if s.iocp, e = syscall.CreateIoCompletionPort(-1, 0, 0, 1); e != 0 {
68 return nil, os.NewSyscallError("CreateIoCompletionPort", e)
74 type ioPacket struct {
75 // Used by IOCP interface,
76 // it must be first field of the struct,
77 // as our code rely on it.
80 // Link to the io owner.
84 func (s *pollServer) getCompletedIO() (ov *syscall.Overlapped, result *ioResult, err os.Error) {
86 var o *syscall.Overlapped
87 _, e := syscall.GetQueuedCompletionStatus(s.iocp, &r.qty, &r.key, &o, syscall.INFINITE)
90 // Dequeued successfully completed io packet.
92 case e == syscall.WAIT_TIMEOUT && o == nil:
93 // Wait has timed out (should not happen now, but might be used in the future).
94 return nil, &r, os.NewSyscallError("GetQueuedCompletionStatus", e)
96 // Failed to dequeue anything -> report the error.
97 return nil, &r, os.NewSyscallError("GetQueuedCompletionStatus", e)
99 // Dequeued failed io packet.
106 func (s *pollServer) Run() {
108 o, r, err := s.getCompletedIO()
110 panic("Run pollServer: " + err.String() + "\n")
112 p := (*ioPacket)(unsafe.Pointer(o))
117 // Network FD methods.
118 // All the network FDs use a single pollServer.
120 var pollserver *pollServer
121 var onceStartServer sync.Once
124 p, err := newPollServer()
126 panic("Start pollServer: " + err.String() + "\n")
133 func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err os.Error) {
137 onceStartServer.Do(startServer)
138 // Associate our socket with pollserver.iocp.
139 if _, e := syscall.CreateIoCompletionPort(int32(fd), pollserver.iocp, 0, 0); e != 0 {
140 return nil, &OpError{"CreateIoCompletionPort", net, laddr, os.Errno(e)}
146 cr: make(chan *ioResult),
147 cw: make(chan *ioResult),
159 f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs)
163 // Add a reference to this fd.
164 func (fd *netFD) incref() {
170 // Remove a reference to this FD and close if we've been asked to do so (and
171 // there are no references left.
172 func (fd *netFD) decref() {
175 if fd.closing && fd.sysref == 0 && fd.sysfd >= 0 {
176 // In case the user has set linger, switch to blocking mode so
177 // the close blocks. As long as this doesn't happen often, we
178 // can handle the extra OS processes. Otherwise we'll need to
179 // use the pollserver for Close too. Sigh.
180 syscall.SetNonblock(fd.sysfd, false)
188 func (fd *netFD) Close() os.Error {
189 if fd == nil || fd.sysfile == nil {
194 syscall.Shutdown(fd.sysfd, syscall.SHUT_RDWR)
200 func newWSABuf(p []byte) *syscall.WSABuf {
203 p0 = (*byte)(unsafe.Pointer(&p[0]))
205 return &syscall.WSABuf{uint32(len(p)), p0}
208 func (fd *netFD) Read(p []byte) (n int, err os.Error) {
213 defer fd.rio.Unlock()
216 if fd.sysfile == nil {
219 // Submit receive request.
224 e := syscall.WSARecv(uint32(fd.sysfd), newWSABuf(p), 1, &done, &flags, &pckt.o, nil)
227 // IO completed immediately, but we need to get our completion message anyway.
228 case syscall.ERROR_IO_PENDING:
229 // IO started, and we have to wait for it's completion.
231 return 0, &OpError{"WSARecv", fd.net, fd.laddr, os.Errno(e)}
233 // Wait for our request to complete.
236 err = &OpError{"WSARecv", fd.net, fd.laddr, os.Errno(r.errno)}
239 if err == nil && n == 0 {
245 func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
246 var r syscall.Sockaddr
250 func (fd *netFD) Write(p []byte) (n int, err os.Error) {
255 defer fd.wio.Unlock()
258 if fd.sysfile == nil {
261 // Submit send request.
265 e := syscall.WSASend(uint32(fd.sysfd), newWSABuf(p), 1, &done, uint32(0), &pckt.o, nil)
268 // IO completed immediately, but we need to get our completion message anyway.
269 case syscall.ERROR_IO_PENDING:
270 // IO started, and we have to wait for it's completion.
272 return 0, &OpError{"WSASend", fd.net, fd.laddr, os.Errno(e)}
274 // Wait for our request to complete.
277 err = &OpError{"WSASend", fd.net, fd.laddr, os.Errno(r.errno)}
283 func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
287 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
288 if fd == nil || fd.sysfile == nil {
289 return nil, os.EINVAL
295 // See ../syscall/exec.go for description of ForkLock.
296 syscall.ForkLock.RLock()
297 s, e := syscall.Socket(fd.family, fd.proto, 0)
299 syscall.ForkLock.RUnlock()
300 return nil, os.Errno(e)
302 syscall.CloseOnExec(s)
303 syscall.ForkLock.RUnlock()
305 // Associate our new socket with IOCP.
306 onceStartServer.Do(startServer)
307 if _, e = syscall.CreateIoCompletionPort(int32(s), pollserver.iocp, 0, 0); e != 0 {
308 return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)}
311 // Submit accept request.
312 // Will use new unique channel here, because, unlike Read or Write,
313 // Accept is expected to be executed by many goroutines simultaniously.
315 pckt.c = make(chan *ioResult)
316 attrs, e := syscall.AcceptIOCP(fd.sysfd, s, &pckt.o)
319 // IO completed immediately, but we need to get our completion message anyway.
320 case syscall.ERROR_IO_PENDING:
321 // IO started, and we have to wait for it's completion.
324 return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(e)}
327 // Wait for peer connection.
331 return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(r.errno)}
334 // Inherit properties of the listening socket.
335 e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, fd.sysfd)
338 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, os.Errno(r.errno)}
341 // Get local and peer addr out of AcceptEx buffer.
342 lsa, rsa := syscall.GetAcceptIOCPSockaddrs(attrs)
344 // Create our netFD and return it for further use.
352 cr: make(chan *ioResult),
353 cw: make(chan *ioResult),
365 f.sysfile = os.NewFile(s, fd.net+":"+ls+"->"+rs)
370 var d syscall.WSAData
371 e := syscall.WSAStartup(uint32(0x101), &d)
373 initErr = os.NewSyscallError("WSAStartup", e)
377 func (fd *netFD) dup() (f *os.File, err os.Error) {
378 // TODO: Implement this
379 return nil, os.NewSyscallError("dup", syscall.EWINDOWS)