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