github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/internal/poll/fd_windows.go (about) 1 // Copyright 2017 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 poll 6 7 import ( 8 "errors" 9 "internal/race" 10 "io" 11 "runtime" 12 "sync" 13 "syscall" 14 "unicode/utf16" 15 "unicode/utf8" 16 "unsafe" 17 ) 18 19 var ( 20 initErr error 21 ioSync uint64 22 ) 23 24 // CancelIo Windows API cancels all outstanding IO for a particular 25 // socket on current thread. To overcome that limitation, we run 26 // special goroutine, locked to OS single thread, that both starts 27 // and cancels IO. It means, there are 2 unavoidable thread switches 28 // for every IO. 29 // Some newer versions of Windows has new CancelIoEx API, that does 30 // not have that limitation and can be used from any thread. This 31 // package uses CancelIoEx API, if present, otherwise it fallback 32 // to CancelIo. 33 34 var ( 35 canCancelIO bool // determines if CancelIoEx API is present 36 skipSyncNotif bool 37 hasLoadSetFileCompletionNotificationModes bool 38 ) 39 40 func init() { 41 var d syscall.WSAData 42 e := syscall.WSAStartup(uint32(0x202), &d) 43 if e != nil { 44 initErr = e 45 } 46 canCancelIO = syscall.LoadCancelIoEx() == nil 47 hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil 48 if hasLoadSetFileCompletionNotificationModes { 49 // It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed: 50 // http://support.microsoft.com/kb/2568167 51 skipSyncNotif = true 52 protos := [2]int32{syscall.IPPROTO_TCP, 0} 53 var buf [32]syscall.WSAProtocolInfo 54 len := uint32(unsafe.Sizeof(buf)) 55 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len) 56 if err != nil { 57 skipSyncNotif = false 58 } else { 59 for i := int32(0); i < n; i++ { 60 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 { 61 skipSyncNotif = false 62 break 63 } 64 } 65 } 66 } 67 } 68 69 // operation contains superset of data necessary to perform all async IO. 70 type operation struct { 71 // Used by IOCP interface, it must be first field 72 // of the struct, as our code rely on it. 73 o syscall.Overlapped 74 75 // fields used by runtime.netpoll 76 runtimeCtx uintptr 77 mode int32 78 errno int32 79 qty uint32 80 81 // fields used only by net package 82 fd *FD 83 errc chan error 84 buf syscall.WSABuf 85 sa syscall.Sockaddr 86 rsa *syscall.RawSockaddrAny 87 rsan int32 88 handle syscall.Handle 89 flags uint32 90 bufs []syscall.WSABuf 91 } 92 93 func (o *operation) InitBuf(buf []byte) { 94 o.buf.Len = uint32(len(buf)) 95 o.buf.Buf = nil 96 if len(buf) != 0 { 97 o.buf.Buf = &buf[0] 98 } 99 } 100 101 func (o *operation) InitBufs(buf *[][]byte) { 102 if o.bufs == nil { 103 o.bufs = make([]syscall.WSABuf, 0, len(*buf)) 104 } else { 105 o.bufs = o.bufs[:0] 106 } 107 for _, b := range *buf { 108 var p *byte 109 if len(b) > 0 { 110 p = &b[0] 111 } 112 o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p}) 113 } 114 } 115 116 // ClearBufs clears all pointers to Buffers parameter captured 117 // by InitBufs, so it can be released by garbage collector. 118 func (o *operation) ClearBufs() { 119 for i := range o.bufs { 120 o.bufs[i].Buf = nil 121 } 122 o.bufs = o.bufs[:0] 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 if !canCancelIO { 158 onceStartServer.Do(startServer) 159 } 160 161 fd := o.fd 162 // Notify runtime netpoll about starting IO. 163 err := fd.pd.prepare(int(o.mode)) 164 if err != nil { 165 return 0, err 166 } 167 // Start IO. 168 if canCancelIO { 169 err = submit(o) 170 } else { 171 // Send request to a special dedicated thread, 172 // so it can stop the IO with CancelIO later. 173 s.req <- ioSrvReq{o, submit} 174 err = <-o.errc 175 } 176 switch err { 177 case nil: 178 // IO completed immediately 179 if o.fd.skipSyncNotif { 180 // No completion message will follow, so return immediately. 181 return int(o.qty), nil 182 } 183 // Need to get our completion message anyway. 184 case syscall.ERROR_IO_PENDING: 185 // IO started, and we have to wait for its completion. 186 err = nil 187 default: 188 return 0, err 189 } 190 // Wait for our request to complete. 191 err = fd.pd.wait(int(o.mode)) 192 if err == nil { 193 // All is good. Extract our IO results and return. 194 if o.errno != 0 { 195 err = syscall.Errno(o.errno) 196 return 0, err 197 } 198 return int(o.qty), nil 199 } 200 // IO is interrupted by "close" or "timeout" 201 netpollErr := err 202 switch netpollErr { 203 case ErrClosing, ErrTimeout: 204 // will deal with those. 205 default: 206 panic("unexpected runtime.netpoll error: " + netpollErr.Error()) 207 } 208 // Cancel our request. 209 if canCancelIO { 210 err := syscall.CancelIoEx(fd.Sysfd, &o.o) 211 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. 212 if err != nil && err != syscall.ERROR_NOT_FOUND { 213 // TODO(brainman): maybe do something else, but panic. 214 panic(err) 215 } 216 } else { 217 s.req <- ioSrvReq{o, nil} 218 <-o.errc 219 } 220 // Wait for cancelation to complete. 221 fd.pd.waitCanceled(int(o.mode)) 222 if o.errno != 0 { 223 err = syscall.Errno(o.errno) 224 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled 225 err = netpollErr 226 } 227 return 0, err 228 } 229 // We issued a cancelation request. But, it seems, IO operation succeeded 230 // before the cancelation request run. We need to treat the IO operation as 231 // succeeded (the bytes are actually sent/recv from network). 232 return int(o.qty), nil 233 } 234 235 // Start helper goroutines. 236 var rsrv, wsrv ioSrv 237 var onceStartServer sync.Once 238 239 func startServer() { 240 // This is called, once, when only the CancelIo API is available. 241 // Start two special goroutines, both locked to an OS thread, 242 // that start and cancel IO requests. 243 // One will process read requests, while the other will do writes. 244 rsrv.req = make(chan ioSrvReq) 245 go rsrv.ProcessRemoteIO() 246 wsrv.req = make(chan ioSrvReq) 247 go wsrv.ProcessRemoteIO() 248 } 249 250 // FD is a file descriptor. The net and os packages embed this type in 251 // a larger type representing a network connection or OS file. 252 type FD struct { 253 // Lock sysfd and serialize access to Read and Write methods. 254 fdmu fdMutex 255 256 // System file descriptor. Immutable until Close. 257 Sysfd syscall.Handle 258 259 // Read operation. 260 rop operation 261 // Write operation. 262 wop operation 263 264 // I/O poller. 265 pd pollDesc 266 267 // Used to implement pread/pwrite. 268 l sync.Mutex 269 270 // For console I/O. 271 isConsole bool 272 lastbits []byte // first few bytes of the last incomplete rune in last write 273 readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole 274 readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8 275 readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read 276 277 skipSyncNotif bool 278 279 // Whether this is a streaming descriptor, as opposed to a 280 // packet-based descriptor like a UDP socket. 281 IsStream bool 282 283 // Whether a zero byte read indicates EOF. This is false for a 284 // message based socket connection. 285 ZeroReadIsEOF bool 286 287 // Whether this is a normal file. 288 isFile bool 289 290 // Whether this is a directory. 291 isDir bool 292 } 293 294 // Init initializes the FD. The Sysfd field should already be set. 295 // This can be called multiple times on a single FD. 296 // The net argument is a network name from the net package (e.g., "tcp"), 297 // or "file" or "console" or "dir". 298 func (fd *FD) Init(net string) (string, error) { 299 if initErr != nil { 300 return "", initErr 301 } 302 303 switch net { 304 case "file": 305 fd.isFile = true 306 case "console": 307 fd.isConsole = true 308 case "dir": 309 fd.isDir = true 310 case "tcp", "tcp4", "tcp6": 311 case "udp", "udp4", "udp6": 312 case "ip", "ip4", "ip6": 313 case "unix", "unixgram", "unixpacket": 314 default: 315 return "", errors.New("internal error: unknown network type " + net) 316 } 317 318 if err := fd.pd.init(fd); err != nil { 319 return "", err 320 } 321 if hasLoadSetFileCompletionNotificationModes { 322 // We do not use events, so we can skip them always. 323 flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE) 324 // It's not safe to skip completion notifications for UDP: 325 // http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx 326 if skipSyncNotif && (net == "tcp" || net == "file") { 327 flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 328 } 329 err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags) 330 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 { 331 fd.skipSyncNotif = true 332 } 333 } 334 // Disable SIO_UDP_CONNRESET behavior. 335 // http://support.microsoft.com/kb/263823 336 switch net { 337 case "udp", "udp4", "udp6": 338 ret := uint32(0) 339 flag := uint32(0) 340 size := uint32(unsafe.Sizeof(flag)) 341 err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0) 342 if err != nil { 343 return "wsaioctl", err 344 } 345 } 346 fd.rop.mode = 'r' 347 fd.wop.mode = 'w' 348 fd.rop.fd = fd 349 fd.wop.fd = fd 350 fd.rop.runtimeCtx = fd.pd.runtimeCtx 351 fd.wop.runtimeCtx = fd.pd.runtimeCtx 352 if !canCancelIO { 353 fd.rop.errc = make(chan error) 354 fd.wop.errc = make(chan error) 355 } 356 return "", nil 357 } 358 359 func (fd *FD) destroy() error { 360 if fd.Sysfd == syscall.InvalidHandle { 361 return syscall.EINVAL 362 } 363 // Poller may want to unregister fd in readiness notification mechanism, 364 // so this must be executed before fd.CloseFunc. 365 fd.pd.close() 366 var err error 367 if fd.isFile || fd.isConsole { 368 err = syscall.CloseHandle(fd.Sysfd) 369 } else if fd.isDir { 370 err = syscall.FindClose(fd.Sysfd) 371 } else { 372 // The net package uses the CloseFunc variable for testing. 373 err = CloseFunc(fd.Sysfd) 374 } 375 fd.Sysfd = syscall.InvalidHandle 376 return err 377 } 378 379 // Close closes the FD. The underlying file descriptor is closed by 380 // the destroy method when there are no remaining references. 381 func (fd *FD) Close() error { 382 if !fd.fdmu.increfAndClose() { 383 return ErrClosing 384 } 385 // unblock pending reader and writer 386 fd.pd.evict() 387 return fd.decref() 388 } 389 390 // Shutdown wraps the shutdown network call. 391 func (fd *FD) Shutdown(how int) error { 392 if err := fd.incref(); err != nil { 393 return err 394 } 395 defer fd.decref() 396 return syscall.Shutdown(fd.Sysfd, how) 397 } 398 399 // Read implements io.Reader. 400 func (fd *FD) Read(buf []byte) (int, error) { 401 if err := fd.readLock(); err != nil { 402 return 0, err 403 } 404 defer fd.readUnlock() 405 406 var n int 407 var err error 408 if fd.isFile || fd.isDir || fd.isConsole { 409 fd.l.Lock() 410 defer fd.l.Unlock() 411 if fd.isConsole { 412 n, err = fd.readConsole(buf) 413 } else { 414 n, err = syscall.Read(fd.Sysfd, buf) 415 } 416 if err != nil { 417 n = 0 418 } 419 } else { 420 o := &fd.rop 421 o.InitBuf(buf) 422 n, err = rsrv.ExecIO(o, "WSARecv", func(o *operation) error { 423 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 424 }) 425 if race.Enabled { 426 race.Acquire(unsafe.Pointer(&ioSync)) 427 } 428 } 429 if len(buf) != 0 { 430 err = fd.eofError(n, err) 431 } 432 return n, err 433 } 434 435 var ReadConsole = syscall.ReadConsole // changed for testing 436 437 // readConsole reads utf16 characters from console File, 438 // encodes them into utf8 and stores them in buffer b. 439 // It returns the number of utf8 bytes read and an error, if any. 440 func (fd *FD) readConsole(b []byte) (int, error) { 441 if len(b) == 0 { 442 return 0, nil 443 } 444 445 if fd.readuint16 == nil { 446 // Note: syscall.ReadConsole fails for very large buffers. 447 // The limit is somewhere around (but not exactly) 16384. 448 // Stay well below. 449 fd.readuint16 = make([]uint16, 0, 10000) 450 fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16)) 451 } 452 453 for fd.readbyteOffset >= len(fd.readbyte) { 454 n := cap(fd.readuint16) - len(fd.readuint16) 455 if n > len(b) { 456 n = len(b) 457 } 458 var nw uint32 459 err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil) 460 if err != nil { 461 return 0, err 462 } 463 uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)] 464 fd.readuint16 = fd.readuint16[:0] 465 buf := fd.readbyte[:0] 466 for i := 0; i < len(uint16s); i++ { 467 r := rune(uint16s[i]) 468 if utf16.IsSurrogate(r) { 469 if i+1 == len(uint16s) { 470 if nw > 0 { 471 // Save half surrogate pair for next time. 472 fd.readuint16 = fd.readuint16[:1] 473 fd.readuint16[0] = uint16(r) 474 break 475 } 476 r = utf8.RuneError 477 } else { 478 r = utf16.DecodeRune(r, rune(uint16s[i+1])) 479 if r != utf8.RuneError { 480 i++ 481 } 482 } 483 } 484 n := utf8.EncodeRune(buf[len(buf):cap(buf)], r) 485 buf = buf[:len(buf)+n] 486 } 487 fd.readbyte = buf 488 fd.readbyteOffset = 0 489 if nw == 0 { 490 break 491 } 492 } 493 494 src := fd.readbyte[fd.readbyteOffset:] 495 var i int 496 for i = 0; i < len(src) && i < len(b); i++ { 497 x := src[i] 498 if x == 0x1A { // Ctrl-Z 499 if i == 0 { 500 fd.readbyteOffset++ 501 } 502 break 503 } 504 b[i] = x 505 } 506 fd.readbyteOffset += i 507 return i, nil 508 } 509 510 // Pread emulates the Unix pread system call. 511 func (fd *FD) Pread(b []byte, off int64) (int, error) { 512 if err := fd.readLock(); err != nil { 513 return 0, err 514 } 515 defer fd.readUnlock() 516 517 fd.l.Lock() 518 defer fd.l.Unlock() 519 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 520 if e != nil { 521 return 0, e 522 } 523 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 524 o := syscall.Overlapped{ 525 OffsetHigh: uint32(off >> 32), 526 Offset: uint32(off), 527 } 528 var done uint32 529 e = syscall.ReadFile(fd.Sysfd, b, &done, &o) 530 if e != nil { 531 done = 0 532 if e == syscall.ERROR_HANDLE_EOF { 533 e = io.EOF 534 } 535 } 536 if len(b) != 0 { 537 e = fd.eofError(int(done), e) 538 } 539 return int(done), e 540 } 541 542 // ReadFrom wraps the recvfrom network call. 543 func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { 544 if len(buf) == 0 { 545 return 0, nil, nil 546 } 547 if err := fd.readLock(); err != nil { 548 return 0, nil, err 549 } 550 defer fd.readUnlock() 551 o := &fd.rop 552 o.InitBuf(buf) 553 n, err := rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { 554 if o.rsa == nil { 555 o.rsa = new(syscall.RawSockaddrAny) 556 } 557 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 558 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 559 }) 560 err = fd.eofError(n, err) 561 if err != nil { 562 return n, nil, err 563 } 564 sa, _ := o.rsa.Sockaddr() 565 return n, sa, nil 566 } 567 568 // Write implements io.Writer. 569 func (fd *FD) Write(buf []byte) (int, error) { 570 if err := fd.writeLock(); err != nil { 571 return 0, err 572 } 573 defer fd.writeUnlock() 574 575 var n int 576 var err error 577 if fd.isFile || fd.isDir || fd.isConsole { 578 fd.l.Lock() 579 defer fd.l.Unlock() 580 if fd.isConsole { 581 n, err = fd.writeConsole(buf) 582 } else { 583 n, err = syscall.Write(fd.Sysfd, buf) 584 } 585 if err != nil { 586 n = 0 587 } 588 } else { 589 if race.Enabled { 590 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 591 } 592 o := &fd.wop 593 o.InitBuf(buf) 594 n, err = wsrv.ExecIO(o, "WSASend", func(o *operation) error { 595 return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 596 }) 597 } 598 return n, err 599 } 600 601 // writeConsole writes len(b) bytes to the console File. 602 // It returns the number of bytes written and an error, if any. 603 func (fd *FD) writeConsole(b []byte) (int, error) { 604 n := len(b) 605 runes := make([]rune, 0, 256) 606 if len(fd.lastbits) > 0 { 607 b = append(fd.lastbits, b...) 608 fd.lastbits = nil 609 610 } 611 for len(b) >= utf8.UTFMax || utf8.FullRune(b) { 612 r, l := utf8.DecodeRune(b) 613 runes = append(runes, r) 614 b = b[l:] 615 } 616 if len(b) > 0 { 617 fd.lastbits = make([]byte, len(b)) 618 copy(fd.lastbits, b) 619 } 620 // syscall.WriteConsole seems to fail, if given large buffer. 621 // So limit the buffer to 16000 characters. This number was 622 // discovered by experimenting with syscall.WriteConsole. 623 const maxWrite = 16000 624 for len(runes) > 0 { 625 m := len(runes) 626 if m > maxWrite { 627 m = maxWrite 628 } 629 chunk := runes[:m] 630 runes = runes[m:] 631 uint16s := utf16.Encode(chunk) 632 for len(uint16s) > 0 { 633 var written uint32 634 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil) 635 if err != nil { 636 return 0, err 637 } 638 uint16s = uint16s[written:] 639 } 640 } 641 return n, nil 642 } 643 644 // Pwrite emulates the Unix pwrite system call. 645 func (fd *FD) Pwrite(b []byte, off int64) (int, error) { 646 if err := fd.writeLock(); err != nil { 647 return 0, err 648 } 649 defer fd.writeUnlock() 650 651 fd.l.Lock() 652 defer fd.l.Unlock() 653 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 654 if e != nil { 655 return 0, e 656 } 657 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 658 o := syscall.Overlapped{ 659 OffsetHigh: uint32(off >> 32), 660 Offset: uint32(off), 661 } 662 var done uint32 663 e = syscall.WriteFile(fd.Sysfd, b, &done, &o) 664 if e != nil { 665 return 0, e 666 } 667 return int(done), nil 668 } 669 670 // Writev emulates the Unix writev system call. 671 func (fd *FD) Writev(buf *[][]byte) (int64, error) { 672 if len(*buf) == 0 { 673 return 0, nil 674 } 675 if err := fd.writeLock(); err != nil { 676 return 0, err 677 } 678 defer fd.writeUnlock() 679 if race.Enabled { 680 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 681 } 682 o := &fd.wop 683 o.InitBufs(buf) 684 n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error { 685 return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil) 686 }) 687 o.ClearBufs() 688 TestHookDidWritev(n) 689 consume(buf, int64(n)) 690 return int64(n), err 691 } 692 693 // WriteTo wraps the sendto network call. 694 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 695 if len(buf) == 0 { 696 return 0, nil 697 } 698 if err := fd.writeLock(); err != nil { 699 return 0, err 700 } 701 defer fd.writeUnlock() 702 o := &fd.wop 703 o.InitBuf(buf) 704 o.sa = sa 705 n, err := wsrv.ExecIO(o, "WSASendto", func(o *operation) error { 706 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 707 }) 708 return n, err 709 } 710 711 // Call ConnectEx. This doesn't need any locking, since it is only 712 // called when the descriptor is first created. This is here rather 713 // than in the net package so that it can use fd.wop. 714 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error { 715 o := &fd.wop 716 o.sa = ra 717 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { 718 return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o) 719 }) 720 return err 721 } 722 723 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) { 724 // Submit accept request. 725 o.handle = s 726 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 727 _, err := rsrv.ExecIO(o, "AcceptEx", func(o *operation) error { 728 return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 729 }) 730 if err != nil { 731 CloseFunc(s) 732 return "acceptex", err 733 } 734 735 // Inherit properties of the listening socket. 736 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd))) 737 if err != nil { 738 CloseFunc(s) 739 return "setsockopt", err 740 } 741 742 return "", nil 743 } 744 745 // Accept handles accepting a socket. The sysSocket parameter is used 746 // to allocate the net socket. 747 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) { 748 if err := fd.readLock(); err != nil { 749 return syscall.InvalidHandle, nil, 0, "", err 750 } 751 defer fd.readUnlock() 752 753 o := &fd.rop 754 var rawsa [2]syscall.RawSockaddrAny 755 for { 756 s, err := sysSocket() 757 if err != nil { 758 return syscall.InvalidHandle, nil, 0, "", err 759 } 760 761 errcall, err := fd.acceptOne(s, rawsa[:], o) 762 if err == nil { 763 return s, rawsa[:], uint32(o.rsan), "", nil 764 } 765 766 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 767 // returned here. These happen if connection reset is received 768 // before AcceptEx could complete. These errors relate to new 769 // connection, not to AcceptEx, so ignore broken connection and 770 // try AcceptEx again for more connections. 771 errno, ok := err.(syscall.Errno) 772 if !ok { 773 return syscall.InvalidHandle, nil, 0, errcall, err 774 } 775 switch errno { 776 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 777 // ignore these and try again 778 default: 779 return syscall.InvalidHandle, nil, 0, errcall, err 780 } 781 } 782 } 783 784 // Seek wraps syscall.Seek. 785 func (fd *FD) Seek(offset int64, whence int) (int64, error) { 786 if err := fd.incref(); err != nil { 787 return 0, err 788 } 789 defer fd.decref() 790 791 fd.l.Lock() 792 defer fd.l.Unlock() 793 794 return syscall.Seek(fd.Sysfd, offset, whence) 795 } 796 797 // FindNextFile wraps syscall.FindNextFile. 798 func (fd *FD) FindNextFile(data *syscall.Win32finddata) error { 799 if err := fd.incref(); err != nil { 800 return err 801 } 802 defer fd.decref() 803 return syscall.FindNextFile(fd.Sysfd, data) 804 } 805 806 // Fchdir wraps syscall.Fchdir. 807 func (fd *FD) Fchdir() error { 808 if err := fd.incref(); err != nil { 809 return err 810 } 811 defer fd.decref() 812 return syscall.Fchdir(fd.Sysfd) 813 } 814 815 // GetFileType wraps syscall.GetFileType. 816 func (fd *FD) GetFileType() (uint32, error) { 817 if err := fd.incref(); err != nil { 818 return 0, err 819 } 820 defer fd.decref() 821 return syscall.GetFileType(fd.Sysfd) 822 } 823 824 // GetFileInformationByHandle wraps GetFileInformationByHandle. 825 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error { 826 if err := fd.incref(); err != nil { 827 return err 828 } 829 defer fd.decref() 830 return syscall.GetFileInformationByHandle(fd.Sysfd, data) 831 }