github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/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), fd.isFile) 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), fd.isFile) 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 ErrNetClosing, ErrFileClosing, 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(fd.isFile) 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 // Call incref, not readLock, because since pread specifies the 513 // offset it is independent from other reads. 514 if err := fd.incref(); err != nil { 515 return 0, err 516 } 517 defer fd.decref() 518 519 fd.l.Lock() 520 defer fd.l.Unlock() 521 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 522 if e != nil { 523 return 0, e 524 } 525 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 526 o := syscall.Overlapped{ 527 OffsetHigh: uint32(off >> 32), 528 Offset: uint32(off), 529 } 530 var done uint32 531 e = syscall.ReadFile(fd.Sysfd, b, &done, &o) 532 if e != nil { 533 done = 0 534 if e == syscall.ERROR_HANDLE_EOF { 535 e = io.EOF 536 } 537 } 538 if len(b) != 0 { 539 e = fd.eofError(int(done), e) 540 } 541 return int(done), e 542 } 543 544 // ReadFrom wraps the recvfrom network call. 545 func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { 546 if len(buf) == 0 { 547 return 0, nil, nil 548 } 549 if err := fd.readLock(); err != nil { 550 return 0, nil, err 551 } 552 defer fd.readUnlock() 553 o := &fd.rop 554 o.InitBuf(buf) 555 n, err := rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { 556 if o.rsa == nil { 557 o.rsa = new(syscall.RawSockaddrAny) 558 } 559 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 560 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 561 }) 562 err = fd.eofError(n, err) 563 if err != nil { 564 return n, nil, err 565 } 566 sa, _ := o.rsa.Sockaddr() 567 return n, sa, nil 568 } 569 570 // Write implements io.Writer. 571 func (fd *FD) Write(buf []byte) (int, error) { 572 if err := fd.writeLock(); err != nil { 573 return 0, err 574 } 575 defer fd.writeUnlock() 576 577 var n int 578 var err error 579 if fd.isFile || fd.isDir || fd.isConsole { 580 fd.l.Lock() 581 defer fd.l.Unlock() 582 if fd.isConsole { 583 n, err = fd.writeConsole(buf) 584 } else { 585 n, err = syscall.Write(fd.Sysfd, buf) 586 } 587 if err != nil { 588 n = 0 589 } 590 } else { 591 if race.Enabled { 592 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 593 } 594 o := &fd.wop 595 o.InitBuf(buf) 596 n, err = wsrv.ExecIO(o, "WSASend", func(o *operation) error { 597 return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 598 }) 599 } 600 return n, err 601 } 602 603 // writeConsole writes len(b) bytes to the console File. 604 // It returns the number of bytes written and an error, if any. 605 func (fd *FD) writeConsole(b []byte) (int, error) { 606 n := len(b) 607 runes := make([]rune, 0, 256) 608 if len(fd.lastbits) > 0 { 609 b = append(fd.lastbits, b...) 610 fd.lastbits = nil 611 612 } 613 for len(b) >= utf8.UTFMax || utf8.FullRune(b) { 614 r, l := utf8.DecodeRune(b) 615 runes = append(runes, r) 616 b = b[l:] 617 } 618 if len(b) > 0 { 619 fd.lastbits = make([]byte, len(b)) 620 copy(fd.lastbits, b) 621 } 622 // syscall.WriteConsole seems to fail, if given large buffer. 623 // So limit the buffer to 16000 characters. This number was 624 // discovered by experimenting with syscall.WriteConsole. 625 const maxWrite = 16000 626 for len(runes) > 0 { 627 m := len(runes) 628 if m > maxWrite { 629 m = maxWrite 630 } 631 chunk := runes[:m] 632 runes = runes[m:] 633 uint16s := utf16.Encode(chunk) 634 for len(uint16s) > 0 { 635 var written uint32 636 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil) 637 if err != nil { 638 return 0, err 639 } 640 uint16s = uint16s[written:] 641 } 642 } 643 return n, nil 644 } 645 646 // Pwrite emulates the Unix pwrite system call. 647 func (fd *FD) Pwrite(b []byte, off int64) (int, error) { 648 // Call incref, not writeLock, because since pwrite specifies the 649 // offset it is independent from other writes. 650 if err := fd.incref(); err != nil { 651 return 0, err 652 } 653 defer fd.decref() 654 655 fd.l.Lock() 656 defer fd.l.Unlock() 657 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 658 if e != nil { 659 return 0, e 660 } 661 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 662 o := syscall.Overlapped{ 663 OffsetHigh: uint32(off >> 32), 664 Offset: uint32(off), 665 } 666 var done uint32 667 e = syscall.WriteFile(fd.Sysfd, b, &done, &o) 668 if e != nil { 669 return 0, e 670 } 671 return int(done), nil 672 } 673 674 // Writev emulates the Unix writev system call. 675 func (fd *FD) Writev(buf *[][]byte) (int64, error) { 676 if len(*buf) == 0 { 677 return 0, nil 678 } 679 if err := fd.writeLock(); err != nil { 680 return 0, err 681 } 682 defer fd.writeUnlock() 683 if race.Enabled { 684 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 685 } 686 o := &fd.wop 687 o.InitBufs(buf) 688 n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error { 689 return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil) 690 }) 691 o.ClearBufs() 692 TestHookDidWritev(n) 693 consume(buf, int64(n)) 694 return int64(n), err 695 } 696 697 // WriteTo wraps the sendto network call. 698 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 699 if len(buf) == 0 { 700 return 0, nil 701 } 702 if err := fd.writeLock(); err != nil { 703 return 0, err 704 } 705 defer fd.writeUnlock() 706 o := &fd.wop 707 o.InitBuf(buf) 708 o.sa = sa 709 n, err := wsrv.ExecIO(o, "WSASendto", func(o *operation) error { 710 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 711 }) 712 return n, err 713 } 714 715 // Call ConnectEx. This doesn't need any locking, since it is only 716 // called when the descriptor is first created. This is here rather 717 // than in the net package so that it can use fd.wop. 718 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error { 719 o := &fd.wop 720 o.sa = ra 721 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { 722 return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o) 723 }) 724 return err 725 } 726 727 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) { 728 // Submit accept request. 729 o.handle = s 730 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 731 _, err := rsrv.ExecIO(o, "AcceptEx", func(o *operation) error { 732 return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 733 }) 734 if err != nil { 735 CloseFunc(s) 736 return "acceptex", err 737 } 738 739 // Inherit properties of the listening socket. 740 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd))) 741 if err != nil { 742 CloseFunc(s) 743 return "setsockopt", err 744 } 745 746 return "", nil 747 } 748 749 // Accept handles accepting a socket. The sysSocket parameter is used 750 // to allocate the net socket. 751 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) { 752 if err := fd.readLock(); err != nil { 753 return syscall.InvalidHandle, nil, 0, "", err 754 } 755 defer fd.readUnlock() 756 757 o := &fd.rop 758 var rawsa [2]syscall.RawSockaddrAny 759 for { 760 s, err := sysSocket() 761 if err != nil { 762 return syscall.InvalidHandle, nil, 0, "", err 763 } 764 765 errcall, err := fd.acceptOne(s, rawsa[:], o) 766 if err == nil { 767 return s, rawsa[:], uint32(o.rsan), "", nil 768 } 769 770 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 771 // returned here. These happen if connection reset is received 772 // before AcceptEx could complete. These errors relate to new 773 // connection, not to AcceptEx, so ignore broken connection and 774 // try AcceptEx again for more connections. 775 errno, ok := err.(syscall.Errno) 776 if !ok { 777 return syscall.InvalidHandle, nil, 0, errcall, err 778 } 779 switch errno { 780 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 781 // ignore these and try again 782 default: 783 return syscall.InvalidHandle, nil, 0, errcall, err 784 } 785 } 786 } 787 788 // Seek wraps syscall.Seek. 789 func (fd *FD) Seek(offset int64, whence int) (int64, error) { 790 if err := fd.incref(); err != nil { 791 return 0, err 792 } 793 defer fd.decref() 794 795 fd.l.Lock() 796 defer fd.l.Unlock() 797 798 return syscall.Seek(fd.Sysfd, offset, whence) 799 } 800 801 // FindNextFile wraps syscall.FindNextFile. 802 func (fd *FD) FindNextFile(data *syscall.Win32finddata) error { 803 if err := fd.incref(); err != nil { 804 return err 805 } 806 defer fd.decref() 807 return syscall.FindNextFile(fd.Sysfd, data) 808 } 809 810 // Fchdir wraps syscall.Fchdir. 811 func (fd *FD) Fchdir() error { 812 if err := fd.incref(); err != nil { 813 return err 814 } 815 defer fd.decref() 816 return syscall.Fchdir(fd.Sysfd) 817 } 818 819 // GetFileType wraps syscall.GetFileType. 820 func (fd *FD) GetFileType() (uint32, error) { 821 if err := fd.incref(); err != nil { 822 return 0, err 823 } 824 defer fd.decref() 825 return syscall.GetFileType(fd.Sysfd) 826 } 827 828 // GetFileInformationByHandle wraps GetFileInformationByHandle. 829 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error { 830 if err := fd.incref(); err != nil { 831 return err 832 } 833 defer fd.decref() 834 return syscall.GetFileInformationByHandle(fd.Sysfd, data) 835 }