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.
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
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
34 canCancelIO
bool // determines if CancelIoEx API is present
36 hasLoadSetFileCompletionNotificationModes
bool
41 e
:= syscall
.WSAStartup(uint32(0x202), &d
)
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
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)
63 for i
:= int32(0); i
< n
; i
++ {
64 if buf
[i
].ServiceFlags1
&syscall
.XP1_IFS_HANDLES
== 0 {
73 func closesocket(s syscall
.Handle
) error
{
74 return syscall
.Closesocket(s
)
77 func canUseConnectEx(net
string) bool {
79 case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
80 // ConnectEx windows API does not support connectionless sockets.
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.
101 // fields used by runtime.netpoll
107 // fields used only by net package
112 rsa
*syscall
.RawSockaddrAny
114 handle syscall
.Handle
118 func (o
*operation
) InitBuf(buf
[]byte) {
119 o
.buf
.Len
= uint32(len(buf
))
126 // ioSrv executes net IO requests.
131 type ioSrvReq
struct {
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
{
146 r
.o
.errc
<- r
.submit(r
.o
)
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
) {
159 // Notify runtime netpoll about starting IO.
160 err
:= fd
.pd
.Prepare(int(o
.mode
))
162 return 0, &OpError
{name
, fd
.net
, fd
.laddr
, err
}
168 // Send request to a special dedicated thread,
169 // so it can stop the IO with CancelIO later.
170 s
.req
<- ioSrvReq
{o
, submit
}
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.
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
))
190 // All is good. Extract our IO results and return.
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"
200 case errClosing
, errTimeout
:
201 // will deal with those.
203 panic("net: unexpected runtime.netpoll error: " + netpollErr
.Error())
205 // Cancel our request.
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.
214 s
.req
<- ioSrvReq
{o
, nil}
217 // Wait for cancellation to complete.
218 fd
.pd
.WaitCanceled(int(o
.mode
))
220 err
= syscall
.Errno(o
.errno
)
221 if err
== syscall
.ERROR_OPERATION_ABORTED
{ // IO Canceled
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
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.
252 // locking/lifetime of sysfd + serialize access to Read and Write methods
255 // immutable until Close
265 rop operation
// read operation
266 wop operation
// write operation
272 func newFD(sysfd syscall
.Handle
, family
, sotype
int, net
string) (*netFD
, error
) {
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 {
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
301 fd
.rop
.runtimeCtx
= fd
.pd
.runtimeCtx
302 fd
.wop
.runtimeCtx
= fd
.pd
.runtimeCtx
304 fd
.rop
.errc
= make(chan error
)
305 fd
.wop
.errc
= make(chan error
)
310 func (fd
*netFD
) setAddr(laddr
, raddr Addr
) {
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 {
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.
333 case *syscall
.SockaddrInet4
:
334 la
= &syscall
.SockaddrInet4
{}
335 case *syscall
.SockaddrInet6
:
336 la
= &syscall
.SockaddrInet6
{}
338 panic("unexpected type in connect")
340 if err
:= syscall
.Bind(fd
.sysfd
, la
); err
!= nil {
344 // Call ConnectEx API.
347 _
, err
:= wsrv
.ExecIO(o
, "ConnectEx", func(o
*operation
) error
{
348 return syscall
.ConnectEx(o
.fd
.sysfd
, o
.sa
, nil, 0, nil, &o
.o
)
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
{
361 // Poller may want to unregister fd in readiness notification mechanism,
362 // so this must be executed before closesocket.
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() {
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() {
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) {
396 // Unlock for reading and remove a reference to this FD.
397 func (fd
*netFD
) readUnlock() {
398 if fd
.fdmu
.RWUnlock(true) {
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) {
412 // Unlock for writing and remove a reference to this FD.
413 func (fd
*netFD
) writeUnlock() {
414 if fd
.fdmu
.RWUnlock(false) {
419 func (fd
*netFD
) Close() error
{
420 if !fd
.fdmu
.IncrefAndClose() {
423 // unblock pending reader and writer
429 func (fd
*netFD
) shutdown(how
int) error
{
430 if err
:= fd
.incref(); err
!= nil {
434 err
:= syscall
.Shutdown(fd
.sysfd
, how
)
436 return &OpError
{"shutdown", fd
.net
, fd
.laddr
, err
}
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 {
453 defer fd
.readUnlock()
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 {
463 raceAcquire(unsafe
.Pointer(&ioSync
))
468 func (fd
*netFD
) readFrom(buf
[]byte) (n
int, sa syscall
.Sockaddr
, err error
) {
472 if err
:= fd
.readLock(); err
!= nil {
475 defer fd
.readUnlock()
478 n
, err
= rsrv
.ExecIO(o
, "WSARecvFrom", func(o
*operation
) error
{
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)
488 sa
, _
= o
.rsa
.Sockaddr()
492 func (fd
*netFD
) Write(buf
[]byte) (int, error
) {
493 if err
:= fd
.writeLock(); err
!= nil {
496 defer fd
.writeUnlock()
498 raceReleaseMerge(unsafe
.Pointer(&ioSync
))
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
) {
511 if err
:= fd
.writeLock(); err
!= nil {
514 defer fd
.writeUnlock()
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
) {
525 s
, err
:= sysSocket(fd
.family
, fd
.sotype
, 0)
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
)
534 return nil, &OpError
{"accept", fd
.net
, fd
.laddr
, err
}
536 if err
:= netfd
.init(); err
!= nil {
541 // Submit accept request.
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
)
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
)))
556 return nil, &OpError
{"Setsockopt", fd
.net
, fd
.laddr
, err
}
562 func (fd
*netFD
) accept(toAddr
func(syscall
.Sockaddr
) Addr
) (*netFD
, error
) {
563 if err
:= fd
.readLock(); err
!= nil {
566 defer fd
.readUnlock()
571 var rawsa
[2]syscall
.RawSockaddrAny
573 netfd
, err
= fd
.acceptOne(toAddr
, rawsa
[:], o
)
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
)
586 errno
, ok
:= operr
.Err
.(syscall
.Errno
)
591 case syscall
.ERROR_NETNAME_DELETED
, syscall
.WSAECONNRESET
:
592 // ignore these and try again
598 // Get local and peer addr out of AcceptEx buffer.
599 var lrsa
, rrsa
*syscall
.RawSockaddrAny
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
))
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
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