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