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