github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/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 "io" 10 "os" 11 "runtime" 12 "sync" 13 "syscall" 14 "time" 15 "unsafe" 16 ) 17 18 var ( 19 initErr error 20 ioSync uint64 21 ) 22 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. 32 33 var ( 34 canCancelIO bool // determines if CancelIoEx API is present 35 skipSyncNotif bool 36 hasLoadSetFileCompletionNotificationModes bool 37 ) 38 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) 44 } 45 canCancelIO = syscall.LoadCancelIoEx() == nil 46 if syscall.LoadGetAddrInfo() == nil { 47 lookupPort = newLookupPort 48 lookupIP = newLookupIP 49 } 50 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 67 } 68 } 69 } 70 } 71 } 72 73 func closesocket(s syscall.Handle) error { 74 return syscall.Closesocket(s) 75 } 76 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 82 } 83 return syscall.LoadConnectEx() == nil 84 } 85 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) 91 } 92 return dialer(deadline) 93 } 94 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 100 101 // fields used by runtime.netpoll 102 runtimeCtx uintptr 103 mode int32 104 errno int32 105 qty uint32 106 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 116 } 117 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] 123 } 124 } 125 126 // ioSrv executes net IO requests. 127 type ioSrv struct { 128 req chan ioSrvReq 129 } 130 131 type ioSrvReq struct { 132 o *operation 133 submit func(o *operation) error // if nil, cancel the operation 134 } 135 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) 149 } 150 } 151 } 152 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} 163 } 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 172 } 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 179 } 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} 186 } 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} 194 } 195 return int(o.qty), nil 196 } 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()) 204 } 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) 212 } 213 } else { 214 s.req <- ioSrvReq{o, nil} 215 <-o.errc 216 } 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 223 } 224 return 0, &OpError{name, fd.net, fd.laddr, err} 225 } 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 230 } 231 232 // Start helper goroutines. 233 var rsrv, wsrv *ioSrv 234 var onceStartServer sync.Once 235 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() 247 } 248 } 249 250 // Network file descriptor. 251 type netFD struct { 252 // locking/lifetime of sysfd + serialize access to Read and Write methods 253 fdmu fdMutex 254 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 264 265 rop operation // read operation 266 wop operation // write operation 267 268 // wait server 269 pd pollDesc 270 } 271 272 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) { 273 if initErr != nil { 274 return nil, initErr 275 } 276 onceStartServer.Do(startServer) 277 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil 278 } 279 280 func (fd *netFD) init() error { 281 if err := fd.pd.Init(fd); err != nil { 282 return err 283 } 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 291 } 292 err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags) 293 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 { 294 fd.skipSyncNotif = true 295 } 296 } 297 // Disable SIO_UDP_CONNRESET behavior. 298 // http://support.microsoft.com/kb/263823 299 switch fd.net { 300 case "udp", "udp4", "udp6": 301 ret := uint32(0) 302 flag := uint32(0) 303 size := uint32(unsafe.Sizeof(flag)) 304 err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0) 305 if err != nil { 306 return os.NewSyscallError("WSAIoctl", err) 307 } 308 } 309 fd.rop.mode = 'r' 310 fd.wop.mode = 'w' 311 fd.rop.fd = fd 312 fd.wop.fd = fd 313 fd.rop.runtimeCtx = fd.pd.runtimeCtx 314 fd.wop.runtimeCtx = fd.pd.runtimeCtx 315 if !canCancelIO { 316 fd.rop.errc = make(chan error) 317 fd.wop.errc = make(chan error) 318 } 319 return nil 320 } 321 322 func (fd *netFD) setAddr(laddr, raddr Addr) { 323 fd.laddr = laddr 324 fd.raddr = raddr 325 runtime.SetFinalizer(fd, (*netFD).Close) 326 } 327 328 func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { 329 // Do not need to call fd.writeLock here, 330 // because fd is not yet accessible to user, 331 // so no concurrent operations are possible. 332 if err := fd.init(); err != nil { 333 return err 334 } 335 if !deadline.IsZero() { 336 fd.setWriteDeadline(deadline) 337 defer fd.setWriteDeadline(noDeadline) 338 } 339 if !canUseConnectEx(fd.net) { 340 return syscall.Connect(fd.sysfd, ra) 341 } 342 // ConnectEx windows API requires an unconnected, previously bound socket. 343 if la == nil { 344 switch ra.(type) { 345 case *syscall.SockaddrInet4: 346 la = &syscall.SockaddrInet4{} 347 case *syscall.SockaddrInet6: 348 la = &syscall.SockaddrInet6{} 349 default: 350 panic("unexpected type in connect") 351 } 352 if err := syscall.Bind(fd.sysfd, la); err != nil { 353 return err 354 } 355 } 356 // Call ConnectEx API. 357 o := &fd.wop 358 o.sa = ra 359 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { 360 return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o) 361 }) 362 if err != nil { 363 return err 364 } 365 // Refresh socket properties. 366 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) 367 } 368 369 func (fd *netFD) destroy() { 370 if fd.sysfd == syscall.InvalidHandle { 371 return 372 } 373 // Poller may want to unregister fd in readiness notification mechanism, 374 // so this must be executed before closesocket. 375 fd.pd.Close() 376 closesocket(fd.sysfd) 377 fd.sysfd = syscall.InvalidHandle 378 // no need for a finalizer anymore 379 runtime.SetFinalizer(fd, nil) 380 } 381 382 // Add a reference to this fd. 383 // Returns an error if the fd cannot be used. 384 func (fd *netFD) incref() error { 385 if !fd.fdmu.Incref() { 386 return errClosing 387 } 388 return nil 389 } 390 391 // Remove a reference to this FD and close if we've been asked to do so 392 // (and there are no references left). 393 func (fd *netFD) decref() { 394 if fd.fdmu.Decref() { 395 fd.destroy() 396 } 397 } 398 399 // Add a reference to this fd and lock for reading. 400 // Returns an error if the fd cannot be used. 401 func (fd *netFD) readLock() error { 402 if !fd.fdmu.RWLock(true) { 403 return errClosing 404 } 405 return nil 406 } 407 408 // Unlock for reading and remove a reference to this FD. 409 func (fd *netFD) readUnlock() { 410 if fd.fdmu.RWUnlock(true) { 411 fd.destroy() 412 } 413 } 414 415 // Add a reference to this fd and lock for writing. 416 // Returns an error if the fd cannot be used. 417 func (fd *netFD) writeLock() error { 418 if !fd.fdmu.RWLock(false) { 419 return errClosing 420 } 421 return nil 422 } 423 424 // Unlock for writing and remove a reference to this FD. 425 func (fd *netFD) writeUnlock() { 426 if fd.fdmu.RWUnlock(false) { 427 fd.destroy() 428 } 429 } 430 431 func (fd *netFD) Close() error { 432 if !fd.fdmu.IncrefAndClose() { 433 return errClosing 434 } 435 // unblock pending reader and writer 436 fd.pd.Evict() 437 fd.decref() 438 return nil 439 } 440 441 func (fd *netFD) shutdown(how int) error { 442 if err := fd.incref(); err != nil { 443 return err 444 } 445 defer fd.decref() 446 err := syscall.Shutdown(fd.sysfd, how) 447 if err != nil { 448 return &OpError{"shutdown", fd.net, fd.laddr, err} 449 } 450 return nil 451 } 452 453 func (fd *netFD) closeRead() error { 454 return fd.shutdown(syscall.SHUT_RD) 455 } 456 457 func (fd *netFD) closeWrite() error { 458 return fd.shutdown(syscall.SHUT_WR) 459 } 460 461 func (fd *netFD) Read(buf []byte) (int, error) { 462 if err := fd.readLock(); err != nil { 463 return 0, err 464 } 465 defer fd.readUnlock() 466 o := &fd.rop 467 o.InitBuf(buf) 468 n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error { 469 return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 470 }) 471 if err == nil && n == 0 { 472 err = io.EOF 473 } 474 if raceenabled { 475 raceAcquire(unsafe.Pointer(&ioSync)) 476 } 477 return n, err 478 } 479 480 func (fd *netFD) readFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { 481 if len(buf) == 0 { 482 return 0, nil, nil 483 } 484 if err := fd.readLock(); err != nil { 485 return 0, nil, err 486 } 487 defer fd.readUnlock() 488 o := &fd.rop 489 o.InitBuf(buf) 490 n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { 491 if o.rsa == nil { 492 o.rsa = new(syscall.RawSockaddrAny) 493 } 494 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 495 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 496 }) 497 if err != nil { 498 return 0, nil, err 499 } 500 sa, _ = o.rsa.Sockaddr() 501 return 502 } 503 504 func (fd *netFD) Write(buf []byte) (int, error) { 505 if err := fd.writeLock(); err != nil { 506 return 0, err 507 } 508 defer fd.writeUnlock() 509 if raceenabled { 510 raceReleaseMerge(unsafe.Pointer(&ioSync)) 511 } 512 o := &fd.wop 513 o.InitBuf(buf) 514 return wsrv.ExecIO(o, "WSASend", func(o *operation) error { 515 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 516 }) 517 } 518 519 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) { 520 if len(buf) == 0 { 521 return 0, nil 522 } 523 if err := fd.writeLock(); err != nil { 524 return 0, err 525 } 526 defer fd.writeUnlock() 527 o := &fd.wop 528 o.InitBuf(buf) 529 o.sa = sa 530 return wsrv.ExecIO(o, "WSASendto", func(o *operation) error { 531 return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 532 }) 533 } 534 535 func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) { 536 // Get new socket. 537 s, err := sysSocket(fd.family, fd.sotype, 0) 538 if err != nil { 539 return nil, &OpError{"socket", fd.net, fd.laddr, err} 540 } 541 542 // Associate our new socket with IOCP. 543 netfd, err := newFD(s, fd.family, fd.sotype, fd.net) 544 if err != nil { 545 closesocket(s) 546 return nil, &OpError{"accept", fd.net, fd.laddr, err} 547 } 548 if err := netfd.init(); err != nil { 549 fd.Close() 550 return nil, err 551 } 552 553 // Submit accept request. 554 o.handle = s 555 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 556 _, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error { 557 return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 558 }) 559 if err != nil { 560 netfd.Close() 561 return nil, err 562 } 563 564 // Inherit properties of the listening socket. 565 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) 566 if err != nil { 567 netfd.Close() 568 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} 569 } 570 571 return netfd, nil 572 } 573 574 func (fd *netFD) accept() (*netFD, error) { 575 if err := fd.readLock(); err != nil { 576 return nil, err 577 } 578 defer fd.readUnlock() 579 580 o := &fd.rop 581 var netfd *netFD 582 var err error 583 var rawsa [2]syscall.RawSockaddrAny 584 for { 585 netfd, err = fd.acceptOne(rawsa[:], o) 586 if err == nil { 587 break 588 } 589 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 590 // returned here. These happen if connection reset is received 591 // before AcceptEx could complete. These errors relate to new 592 // connection, not to AcceptEx, so ignore broken connection and 593 // try AcceptEx again for more connections. 594 operr, ok := err.(*OpError) 595 if !ok { 596 return nil, err 597 } 598 errno, ok := operr.Err.(syscall.Errno) 599 if !ok { 600 return nil, err 601 } 602 switch errno { 603 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 604 // ignore these and try again 605 default: 606 return nil, err 607 } 608 } 609 610 // Get local and peer addr out of AcceptEx buffer. 611 var lrsa, rrsa *syscall.RawSockaddrAny 612 var llen, rlen int32 613 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])), 614 0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen) 615 lsa, _ := lrsa.Sockaddr() 616 rsa, _ := rrsa.Sockaddr() 617 618 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 619 return netfd, nil 620 } 621 622 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 623 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx: 624 // Note: To use a socket of type SOCK_RAW requires administrative privileges. 625 // Users running Winsock applications that use raw sockets must be a member of 626 // the Administrators group on the local computer, otherwise raw socket calls 627 // will fail with an error code of WSAEACCES. On Windows Vista and later, access 628 // for raw sockets is enforced at socket creation. In earlier versions of Windows, 629 // access for raw sockets is enforced during other socket operations. 630 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0) 631 if err == syscall.WSAEACCES { 632 return true, "skipping test; no access to raw socket allowed", nil 633 } 634 if err != nil { 635 return true, "", err 636 } 637 defer syscall.Closesocket(s) 638 return false, "", nil 639 } 640 641 // Unimplemented functions. 642 643 func (fd *netFD) dup() (*os.File, error) { 644 // TODO: Implement this 645 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) 646 } 647 648 var errNoSupport = errors.New("address family not supported") 649 650 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 651 return 0, 0, 0, nil, errNoSupport 652 } 653 654 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 655 return 0, 0, errNoSupport 656 }