Revert r215321.
[official-gcc.git] / libgo / go / net / fd_windows.go
blobd1129dccc47d8a857d038cf5758b794f5dacd80b
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.
5 package net
7 import (
8 "errors"
9 "io"
10 "os"
11 "runtime"
12 "sync"
13 "syscall"
14 "time"
15 "unsafe"
18 var (
19 initErr error
20 ioSync uint64
23 // CancelIo Windows API cancels all outstanding IO for a particular
24 // socket on current thread. To overcome that limitation, we run
25 // special goroutine, locked to OS single thread, that both starts
26 // and cancels IO. It means, there are 2 unavoidable thread switches
27 // for every IO.
28 // Some newer versions of Windows has new CancelIoEx API, that does
29 // not have that limitation and can be used from any thread. This
30 // package uses CancelIoEx API, if present, otherwise it fallback
31 // to CancelIo.
33 var (
34 canCancelIO bool // determines if CancelIoEx API is present
35 skipSyncNotif bool
36 hasLoadSetFileCompletionNotificationModes bool
39 func sysInit() {
40 var d syscall.WSAData
41 e := syscall.WSAStartup(uint32(0x202), &d)
42 if e != nil {
43 initErr = os.NewSyscallError("WSAStartup", e)
45 canCancelIO = syscall.LoadCancelIoEx() == nil
46 if syscall.LoadGetAddrInfo() == nil {
47 lookupPort = newLookupPort
48 lookupIP = newLookupIP
51 hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
52 if hasLoadSetFileCompletionNotificationModes {
53 // It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
54 // http://support.microsoft.com/kb/2568167
55 skipSyncNotif = true
56 protos := [2]int32{syscall.IPPROTO_TCP, 0}
57 var buf [32]syscall.WSAProtocolInfo
58 len := uint32(unsafe.Sizeof(buf))
59 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
60 if err != nil {
61 skipSyncNotif = false
62 } else {
63 for i := int32(0); i < n; i++ {
64 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
65 skipSyncNotif = false
66 break
73 func closesocket(s syscall.Handle) error {
74 return syscall.Closesocket(s)
77 func canUseConnectEx(net string) bool {
78 switch net {
79 case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
80 // ConnectEx windows API does not support connectionless sockets.
81 return false
83 return syscall.LoadConnectEx() == nil
86 func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
87 if !canUseConnectEx(net) {
88 // Use the relatively inefficient goroutine-racing
89 // implementation of DialTimeout.
90 return dialChannel(net, ra, dialer, deadline)
92 return dialer(deadline)
95 // operation contains superset of data necessary to perform all async IO.
96 type operation struct {
97 // Used by IOCP interface, it must be first field
98 // of the struct, as our code rely on it.
99 o syscall.Overlapped
101 // fields used by runtime.netpoll
102 runtimeCtx uintptr
103 mode int32
104 errno int32
105 qty uint32
107 // fields used only by net package
108 fd *netFD
109 errc chan error
110 buf syscall.WSABuf
111 sa syscall.Sockaddr
112 rsa *syscall.RawSockaddrAny
113 rsan int32
114 handle syscall.Handle
115 flags uint32
118 func (o *operation) InitBuf(buf []byte) {
119 o.buf.Len = uint32(len(buf))
120 o.buf.Buf = nil
121 if len(buf) != 0 {
122 o.buf.Buf = &buf[0]
126 // ioSrv executes net IO requests.
127 type ioSrv struct {
128 req chan ioSrvReq
131 type ioSrvReq struct {
132 o *operation
133 submit func(o *operation) error // if nil, cancel the operation
136 // ProcessRemoteIO will execute submit IO requests on behalf
137 // of other goroutines, all on a single os thread, so it can
138 // cancel them later. Results of all operations will be sent
139 // back to their requesters via channel supplied in request.
140 // It is used only when the CancelIoEx API is unavailable.
141 func (s *ioSrv) ProcessRemoteIO() {
142 runtime.LockOSThread()
143 defer runtime.UnlockOSThread()
144 for r := range s.req {
145 if r.submit != nil {
146 r.o.errc <- r.submit(r.o)
147 } else {
148 r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
153 // ExecIO executes a single IO operation o. It submits and cancels
154 // IO in the current thread for systems where Windows CancelIoEx API
155 // is available. Alternatively, it passes the request onto
156 // runtime netpoll and waits for completion or cancels request.
157 func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
158 fd := o.fd
159 // Notify runtime netpoll about starting IO.
160 err := fd.pd.Prepare(int(o.mode))
161 if err != nil {
162 return 0, &OpError{name, fd.net, fd.laddr, err}
164 // Start IO.
165 if canCancelIO {
166 err = submit(o)
167 } else {
168 // Send request to a special dedicated thread,
169 // so it can stop the IO with CancelIO later.
170 s.req <- ioSrvReq{o, submit}
171 err = <-o.errc
173 switch err {
174 case nil:
175 // IO completed immediately
176 if o.fd.skipSyncNotif {
177 // No completion message will follow, so return immediately.
178 return int(o.qty), nil
180 // Need to get our completion message anyway.
181 case syscall.ERROR_IO_PENDING:
182 // IO started, and we have to wait for its completion.
183 err = nil
184 default:
185 return 0, &OpError{name, fd.net, fd.laddr, err}
187 // Wait for our request to complete.
188 err = fd.pd.Wait(int(o.mode))
189 if err == nil {
190 // All is good. Extract our IO results and return.
191 if o.errno != 0 {
192 err = syscall.Errno(o.errno)
193 return 0, &OpError{name, fd.net, fd.laddr, err}
195 return int(o.qty), nil
197 // IO is interrupted by "close" or "timeout"
198 netpollErr := err
199 switch netpollErr {
200 case errClosing, errTimeout:
201 // will deal with those.
202 default:
203 panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
205 // Cancel our request.
206 if canCancelIO {
207 err := syscall.CancelIoEx(fd.sysfd, &o.o)
208 // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
209 if err != nil && err != syscall.ERROR_NOT_FOUND {
210 // TODO(brainman): maybe do something else, but panic.
211 panic(err)
213 } else {
214 s.req <- ioSrvReq{o, nil}
215 <-o.errc
217 // Wait for cancellation to complete.
218 fd.pd.WaitCanceled(int(o.mode))
219 if o.errno != 0 {
220 err = syscall.Errno(o.errno)
221 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
222 err = netpollErr
224 return 0, &OpError{name, fd.net, fd.laddr, err}
226 // We issued cancellation request. But, it seems, IO operation succeeded
227 // before cancellation request run. We need to treat IO operation as
228 // succeeded (the bytes are actually sent/recv from network).
229 return int(o.qty), nil
232 // Start helper goroutines.
233 var rsrv, wsrv *ioSrv
234 var onceStartServer sync.Once
236 func startServer() {
237 rsrv = new(ioSrv)
238 wsrv = new(ioSrv)
239 if !canCancelIO {
240 // Only CancelIo API is available. Lets start two special goroutines
241 // locked to an OS thread, that both starts and cancels IO. One will
242 // process read requests, while other will do writes.
243 rsrv.req = make(chan ioSrvReq)
244 go rsrv.ProcessRemoteIO()
245 wsrv.req = make(chan ioSrvReq)
246 go wsrv.ProcessRemoteIO()
250 // Network file descriptor.
251 type netFD struct {
252 // locking/lifetime of sysfd + serialize access to Read and Write methods
253 fdmu fdMutex
255 // immutable until Close
256 sysfd syscall.Handle
257 family int
258 sotype int
259 isConnected bool
260 skipSyncNotif bool
261 net string
262 laddr Addr
263 raddr Addr
265 rop operation // read operation
266 wop operation // write operation
268 // wait server
269 pd pollDesc
272 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
273 if initErr != nil {
274 return nil, initErr
276 onceStartServer.Do(startServer)
277 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
280 func (fd *netFD) init() error {
281 if err := fd.pd.Init(fd); err != nil {
282 return err
284 if hasLoadSetFileCompletionNotificationModes {
285 // We do not use events, so we can skip them always.
286 flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
287 // It's not safe to skip completion notifications for UDP:
288 // http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
289 if skipSyncNotif && fd.net == "tcp" {
290 flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
292 err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
293 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
294 fd.skipSyncNotif = true
297 fd.rop.mode = 'r'
298 fd.wop.mode = 'w'
299 fd.rop.fd = fd
300 fd.wop.fd = fd
301 fd.rop.runtimeCtx = fd.pd.runtimeCtx
302 fd.wop.runtimeCtx = fd.pd.runtimeCtx
303 if !canCancelIO {
304 fd.rop.errc = make(chan error)
305 fd.wop.errc = make(chan error)
307 return nil
310 func (fd *netFD) setAddr(laddr, raddr Addr) {
311 fd.laddr = laddr
312 fd.raddr = raddr
313 runtime.SetFinalizer(fd, (*netFD).Close)
316 func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
317 // Do not need to call fd.writeLock here,
318 // because fd is not yet accessible to user,
319 // so no concurrent operations are possible.
320 if err := fd.init(); err != nil {
321 return err
323 if !deadline.IsZero() {
324 fd.setWriteDeadline(deadline)
325 defer fd.setWriteDeadline(noDeadline)
327 if !canUseConnectEx(fd.net) {
328 return syscall.Connect(fd.sysfd, ra)
330 // ConnectEx windows API requires an unconnected, previously bound socket.
331 if la == nil {
332 switch ra.(type) {
333 case *syscall.SockaddrInet4:
334 la = &syscall.SockaddrInet4{}
335 case *syscall.SockaddrInet6:
336 la = &syscall.SockaddrInet6{}
337 default:
338 panic("unexpected type in connect")
340 if err := syscall.Bind(fd.sysfd, la); err != nil {
341 return err
344 // Call ConnectEx API.
345 o := &fd.wop
346 o.sa = ra
347 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
348 return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
350 if err != nil {
351 return err
353 // Refresh socket properties.
354 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
357 func (fd *netFD) destroy() {
358 if fd.sysfd == syscall.InvalidHandle {
359 return
361 // Poller may want to unregister fd in readiness notification mechanism,
362 // so this must be executed before closesocket.
363 fd.pd.Close()
364 closesocket(fd.sysfd)
365 fd.sysfd = syscall.InvalidHandle
366 // no need for a finalizer anymore
367 runtime.SetFinalizer(fd, nil)
370 // Add a reference to this fd.
371 // Returns an error if the fd cannot be used.
372 func (fd *netFD) incref() error {
373 if !fd.fdmu.Incref() {
374 return errClosing
376 return nil
379 // Remove a reference to this FD and close if we've been asked to do so
380 // (and there are no references left).
381 func (fd *netFD) decref() {
382 if fd.fdmu.Decref() {
383 fd.destroy()
387 // Add a reference to this fd and lock for reading.
388 // Returns an error if the fd cannot be used.
389 func (fd *netFD) readLock() error {
390 if !fd.fdmu.RWLock(true) {
391 return errClosing
393 return nil
396 // Unlock for reading and remove a reference to this FD.
397 func (fd *netFD) readUnlock() {
398 if fd.fdmu.RWUnlock(true) {
399 fd.destroy()
403 // Add a reference to this fd and lock for writing.
404 // Returns an error if the fd cannot be used.
405 func (fd *netFD) writeLock() error {
406 if !fd.fdmu.RWLock(false) {
407 return errClosing
409 return nil
412 // Unlock for writing and remove a reference to this FD.
413 func (fd *netFD) writeUnlock() {
414 if fd.fdmu.RWUnlock(false) {
415 fd.destroy()
419 func (fd *netFD) Close() error {
420 if !fd.fdmu.IncrefAndClose() {
421 return errClosing
423 // unblock pending reader and writer
424 fd.pd.Evict()
425 fd.decref()
426 return nil
429 func (fd *netFD) shutdown(how int) error {
430 if err := fd.incref(); err != nil {
431 return err
433 defer fd.decref()
434 err := syscall.Shutdown(fd.sysfd, how)
435 if err != nil {
436 return &OpError{"shutdown", fd.net, fd.laddr, err}
438 return nil
441 func (fd *netFD) closeRead() error {
442 return fd.shutdown(syscall.SHUT_RD)
445 func (fd *netFD) closeWrite() error {
446 return fd.shutdown(syscall.SHUT_WR)
449 func (fd *netFD) Read(buf []byte) (int, error) {
450 if err := fd.readLock(); err != nil {
451 return 0, err
453 defer fd.readUnlock()
454 o := &fd.rop
455 o.InitBuf(buf)
456 n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
457 return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
459 if err == nil && n == 0 {
460 err = io.EOF
462 if raceenabled {
463 raceAcquire(unsafe.Pointer(&ioSync))
465 return n, err
468 func (fd *netFD) readFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
469 if len(buf) == 0 {
470 return 0, nil, nil
472 if err := fd.readLock(); err != nil {
473 return 0, nil, err
475 defer fd.readUnlock()
476 o := &fd.rop
477 o.InitBuf(buf)
478 n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
479 if o.rsa == nil {
480 o.rsa = new(syscall.RawSockaddrAny)
482 o.rsan = int32(unsafe.Sizeof(*o.rsa))
483 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
485 if err != nil {
486 return 0, nil, err
488 sa, _ = o.rsa.Sockaddr()
489 return
492 func (fd *netFD) Write(buf []byte) (int, error) {
493 if err := fd.writeLock(); err != nil {
494 return 0, err
496 defer fd.writeUnlock()
497 if raceenabled {
498 raceReleaseMerge(unsafe.Pointer(&ioSync))
500 o := &fd.wop
501 o.InitBuf(buf)
502 return wsrv.ExecIO(o, "WSASend", func(o *operation) error {
503 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
507 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
508 if len(buf) == 0 {
509 return 0, nil
511 if err := fd.writeLock(); err != nil {
512 return 0, err
514 defer fd.writeUnlock()
515 o := &fd.wop
516 o.InitBuf(buf)
517 o.sa = sa
518 return wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
519 return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
523 func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
524 // Get new socket.
525 s, err := sysSocket(fd.family, fd.sotype, 0)
526 if err != nil {
527 return nil, &OpError{"socket", fd.net, fd.laddr, err}
530 // Associate our new socket with IOCP.
531 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
532 if err != nil {
533 closesocket(s)
534 return nil, &OpError{"accept", fd.net, fd.laddr, err}
536 if err := netfd.init(); err != nil {
537 fd.Close()
538 return nil, err
541 // Submit accept request.
542 o.handle = s
543 o.rsan = int32(unsafe.Sizeof(rawsa[0]))
544 _, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
545 return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
547 if err != nil {
548 netfd.Close()
549 return nil, err
552 // Inherit properties of the listening socket.
553 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
554 if err != nil {
555 netfd.Close()
556 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
559 return netfd, nil
562 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
563 if err := fd.readLock(); err != nil {
564 return nil, err
566 defer fd.readUnlock()
568 o := &fd.rop
569 var netfd *netFD
570 var err error
571 var rawsa [2]syscall.RawSockaddrAny
572 for {
573 netfd, err = fd.acceptOne(toAddr, rawsa[:], o)
574 if err == nil {
575 break
577 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
578 // returned here. These happen if connection reset is received
579 // before AcceptEx could complete. These errors relate to new
580 // connection, not to AcceptEx, so ignore broken connection and
581 // try AcceptEx again for more connections.
582 operr, ok := err.(*OpError)
583 if !ok {
584 return nil, err
586 errno, ok := operr.Err.(syscall.Errno)
587 if !ok {
588 return nil, err
590 switch errno {
591 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
592 // ignore these and try again
593 default:
594 return nil, err
598 // Get local and peer addr out of AcceptEx buffer.
599 var lrsa, rrsa *syscall.RawSockaddrAny
600 var llen, rlen int32
601 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
602 0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
603 lsa, _ := lrsa.Sockaddr()
604 rsa, _ := rrsa.Sockaddr()
606 netfd.setAddr(toAddr(lsa), toAddr(rsa))
607 return netfd, nil
610 func skipRawSocketTests() (skip bool, skipmsg string, err error) {
611 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
612 // Note: To use a socket of type SOCK_RAW requires administrative privileges.
613 // Users running Winsock applications that use raw sockets must be a member of
614 // the Administrators group on the local computer, otherwise raw socket calls
615 // will fail with an error code of WSAEACCES. On Windows Vista and later, access
616 // for raw sockets is enforced at socket creation. In earlier versions of Windows,
617 // access for raw sockets is enforced during other socket operations.
618 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
619 if err == syscall.WSAEACCES {
620 return true, "skipping test; no access to raw socket allowed", nil
622 if err != nil {
623 return true, "", err
625 defer syscall.Closesocket(s)
626 return false, "", nil
629 // Unimplemented functions.
631 func (fd *netFD) dup() (*os.File, error) {
632 // TODO: Implement this
633 return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
636 var errNoSupport = errors.New("address family not supported")
638 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
639 return 0, 0, 0, nil, errNoSupport
642 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
643 return 0, 0, errNoSupport