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