github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/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 "github.com/icodeface/tls/internal/race" 10 "github.com/icodeface/tls/internal/syscall/windows" 11 "io" 12 "runtime" 13 "sync" 14 "syscall" 15 "unicode/utf16" 16 "unicode/utf8" 17 "unsafe" 18 ) 19 20 var ( 21 initErr error 22 ioSync uint64 23 ) 24 25 // CancelIo Windows API cancels all outstanding IO for a particular 26 // socket on current thread. To overcome that limitation, we run 27 // special goroutine, locked to OS single thread, that both starts 28 // and cancels IO. It means, there are 2 unavoidable thread switches 29 // for every IO. 30 // Some newer versions of Windows has new CancelIoEx API, that does 31 // not have that limitation and can be used from any thread. This 32 // package uses CancelIoEx API, if present, otherwise it fallback 33 // to CancelIo. 34 35 var canCancelIO bool // determines if CancelIoEx API is present 36 37 // This package uses the SetFileCompletionNotificationModes Windows 38 // API to skip calling GetQueuedCompletionStatus if an IO operation 39 // completes synchronously. There is a known bug where 40 // SetFileCompletionNotificationModes crashes on some systems (see 41 // https://support.microsoft.com/kb/2568167 for details). 42 43 var useSetFileCompletionNotificationModes bool // determines is SetFileCompletionNotificationModes is present and safe to use 44 45 // checkSetFileCompletionNotificationModes verifies that 46 // SetFileCompletionNotificationModes Windows API is present 47 // on the system and is safe to use. 48 // See https://support.microsoft.com/kb/2568167 for details. 49 func checkSetFileCompletionNotificationModes() { 50 err := syscall.LoadSetFileCompletionNotificationModes() 51 if err != nil { 52 return 53 } 54 protos := [2]int32{syscall.IPPROTO_TCP, 0} 55 var buf [32]syscall.WSAProtocolInfo 56 len := uint32(unsafe.Sizeof(buf)) 57 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len) 58 if err != nil { 59 return 60 } 61 for i := int32(0); i < n; i++ { 62 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 { 63 return 64 } 65 } 66 useSetFileCompletionNotificationModes = true 67 } 68 69 func init() { 70 var d syscall.WSAData 71 e := syscall.WSAStartup(uint32(0x202), &d) 72 if e != nil { 73 initErr = e 74 } 75 canCancelIO = syscall.LoadCancelIoEx() == nil 76 checkSetFileCompletionNotificationModes() 77 } 78 79 // operation contains superset of data necessary to perform all async IO. 80 type operation struct { 81 // Used by IOCP interface, it must be first field 82 // of the struct, as our code rely on it. 83 o syscall.Overlapped 84 85 // fields used by runtime.netpoll 86 runtimeCtx uintptr 87 mode int32 88 errno int32 89 qty uint32 90 91 // fields used only by net package 92 fd *FD 93 errc chan error 94 buf syscall.WSABuf 95 msg windows.WSAMsg 96 sa syscall.Sockaddr 97 rsa *syscall.RawSockaddrAny 98 rsan int32 99 handle syscall.Handle 100 flags uint32 101 bufs []syscall.WSABuf 102 } 103 104 func (o *operation) InitBuf(buf []byte) { 105 o.buf.Len = uint32(len(buf)) 106 o.buf.Buf = nil 107 if len(buf) != 0 { 108 o.buf.Buf = &buf[0] 109 } 110 } 111 112 func (o *operation) InitBufs(buf *[][]byte) { 113 if o.bufs == nil { 114 o.bufs = make([]syscall.WSABuf, 0, len(*buf)) 115 } else { 116 o.bufs = o.bufs[:0] 117 } 118 for _, b := range *buf { 119 if len(b) == 0 { 120 o.bufs = append(o.bufs, syscall.WSABuf{}) 121 continue 122 } 123 for len(b) > maxRW { 124 o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]}) 125 b = b[maxRW:] 126 } 127 if len(b) > 0 { 128 o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]}) 129 } 130 } 131 } 132 133 // ClearBufs clears all pointers to Buffers parameter captured 134 // by InitBufs, so it can be released by garbage collector. 135 func (o *operation) ClearBufs() { 136 for i := range o.bufs { 137 o.bufs[i].Buf = nil 138 } 139 o.bufs = o.bufs[:0] 140 } 141 142 func (o *operation) InitMsg(p []byte, oob []byte) { 143 o.InitBuf(p) 144 o.msg.Buffers = &o.buf 145 o.msg.BufferCount = 1 146 147 o.msg.Name = nil 148 o.msg.Namelen = 0 149 150 o.msg.Flags = 0 151 o.msg.Control.Len = uint32(len(oob)) 152 o.msg.Control.Buf = nil 153 if len(oob) != 0 { 154 o.msg.Control.Buf = &oob[0] 155 } 156 } 157 158 // ioSrv executes net IO requests. 159 type ioSrv struct { 160 req chan ioSrvReq 161 } 162 163 type ioSrvReq struct { 164 o *operation 165 submit func(o *operation) error // if nil, cancel the operation 166 } 167 168 // ProcessRemoteIO will execute submit IO requests on behalf 169 // of other goroutines, all on a single os thread, so it can 170 // cancel them later. Results of all operations will be sent 171 // back to their requesters via channel supplied in request. 172 // It is used only when the CancelIoEx API is unavailable. 173 func (s *ioSrv) ProcessRemoteIO() { 174 runtime.LockOSThread() 175 defer runtime.UnlockOSThread() 176 for r := range s.req { 177 if r.submit != nil { 178 r.o.errc <- r.submit(r.o) 179 } else { 180 r.o.errc <- syscall.CancelIo(r.o.fd.Sysfd) 181 } 182 } 183 } 184 185 // ExecIO executes a single IO operation o. It submits and cancels 186 // IO in the current thread for systems where Windows CancelIoEx API 187 // is available. Alternatively, it passes the request onto 188 // runtime netpoll and waits for completion or cancels request. 189 func (s *ioSrv) ExecIO(o *operation, submit func(o *operation) error) (int, error) { 190 if o.fd.pd.runtimeCtx == 0 { 191 return 0, errors.New("internal error: polling on unsupported descriptor type") 192 } 193 194 if !canCancelIO { 195 onceStartServer.Do(startServer) 196 } 197 198 fd := o.fd 199 // Notify runtime netpoll about starting IO. 200 err := fd.pd.prepare(int(o.mode), fd.isFile) 201 if err != nil { 202 return 0, err 203 } 204 // Start IO. 205 if canCancelIO { 206 err = submit(o) 207 } else { 208 // Send request to a special dedicated thread, 209 // so it can stop the IO with CancelIO later. 210 s.req <- ioSrvReq{o, submit} 211 err = <-o.errc 212 } 213 switch err { 214 case nil: 215 // IO completed immediately 216 if o.fd.skipSyncNotif { 217 // No completion message will follow, so return immediately. 218 return int(o.qty), nil 219 } 220 // Need to get our completion message anyway. 221 case syscall.ERROR_IO_PENDING: 222 // IO started, and we have to wait for its completion. 223 err = nil 224 default: 225 return 0, err 226 } 227 // Wait for our request to complete. 228 err = fd.pd.wait(int(o.mode), fd.isFile) 229 if err == nil { 230 // All is good. Extract our IO results and return. 231 if o.errno != 0 { 232 err = syscall.Errno(o.errno) 233 // More data available. Return back the size of received data. 234 if err == syscall.ERROR_MORE_DATA || err == windows.WSAEMSGSIZE { 235 return int(o.qty), err 236 } 237 return 0, err 238 } 239 return int(o.qty), nil 240 } 241 // IO is interrupted by "close" or "timeout" 242 netpollErr := err 243 switch netpollErr { 244 case ErrNetClosing, ErrFileClosing, ErrTimeout: 245 // will deal with those. 246 default: 247 panic("unexpected runtime.netpoll error: " + netpollErr.Error()) 248 } 249 // Cancel our request. 250 if canCancelIO { 251 err := syscall.CancelIoEx(fd.Sysfd, &o.o) 252 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. 253 if err != nil && err != syscall.ERROR_NOT_FOUND { 254 // TODO(brainman): maybe do something else, but panic. 255 panic(err) 256 } 257 } else { 258 s.req <- ioSrvReq{o, nil} 259 <-o.errc 260 } 261 // Wait for cancelation to complete. 262 fd.pd.waitCanceled(int(o.mode)) 263 if o.errno != 0 { 264 err = syscall.Errno(o.errno) 265 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled 266 err = netpollErr 267 } 268 return 0, err 269 } 270 // We issued a cancelation request. But, it seems, IO operation succeeded 271 // before the cancelation request run. We need to treat the IO operation as 272 // succeeded (the bytes are actually sent/recv from network). 273 return int(o.qty), nil 274 } 275 276 // Start helper goroutines. 277 var rsrv, wsrv ioSrv 278 var onceStartServer sync.Once 279 280 func startServer() { 281 // This is called, once, when only the CancelIo API is available. 282 // Start two special goroutines, both locked to an OS thread, 283 // that start and cancel IO requests. 284 // One will process read requests, while the other will do writes. 285 rsrv.req = make(chan ioSrvReq) 286 go rsrv.ProcessRemoteIO() 287 wsrv.req = make(chan ioSrvReq) 288 go wsrv.ProcessRemoteIO() 289 } 290 291 // FD is a file descriptor. The net and os packages embed this type in 292 // a larger type representing a network connection or OS file. 293 type FD struct { 294 // Lock sysfd and serialize access to Read and Write methods. 295 fdmu fdMutex 296 297 // System file descriptor. Immutable until Close. 298 Sysfd syscall.Handle 299 300 // Read operation. 301 rop operation 302 // Write operation. 303 wop operation 304 305 // I/O poller. 306 pd pollDesc 307 308 // Used to implement pread/pwrite. 309 l sync.Mutex 310 311 // For console I/O. 312 isConsole bool 313 lastbits []byte // first few bytes of the last incomplete rune in last write 314 readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole 315 readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8 316 readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read 317 318 // Semaphore signaled when file is closed. 319 csema uint32 320 321 skipSyncNotif bool 322 323 // Whether this is a streaming descriptor, as opposed to a 324 // packet-based descriptor like a UDP socket. 325 IsStream bool 326 327 // Whether a zero byte read indicates EOF. This is false for a 328 // message based socket connection. 329 ZeroReadIsEOF bool 330 331 // Whether this is a normal file. 332 isFile bool 333 334 // Whether this is a directory. 335 isDir bool 336 } 337 338 // logInitFD is set by tests to enable file descriptor initialization logging. 339 var logInitFD func(net string, fd *FD, err error) 340 341 // Init initializes the FD. The Sysfd field should already be set. 342 // This can be called multiple times on a single FD. 343 // The net argument is a network name from the net package (e.g., "tcp"), 344 // or "file" or "console" or "dir". 345 // Set pollable to true if fd should be managed by runtime netpoll. 346 func (fd *FD) Init(net string, pollable bool) (string, error) { 347 if initErr != nil { 348 return "", initErr 349 } 350 351 switch net { 352 case "file": 353 fd.isFile = true 354 case "console": 355 fd.isConsole = true 356 case "dir": 357 fd.isDir = true 358 case "tcp", "tcp4", "tcp6": 359 case "udp", "udp4", "udp6": 360 case "ip", "ip4", "ip6": 361 case "unix", "unixgram", "unixpacket": 362 default: 363 return "", errors.New("internal error: unknown network type " + net) 364 } 365 366 var err error 367 if pollable { 368 // Only call init for a network socket. 369 // This means that we don't add files to the runtime poller. 370 // Adding files to the runtime poller can confuse matters 371 // if the user is doing their own overlapped I/O. 372 // See issue #21172. 373 // 374 // In general the code below avoids calling the ExecIO 375 // method for non-network sockets. If some method does 376 // somehow call ExecIO, then ExecIO, and therefore the 377 // calling method, will return an error, because 378 // fd.pd.runtimeCtx will be 0. 379 err = fd.pd.init(fd) 380 } 381 if logInitFD != nil { 382 logInitFD(net, fd, err) 383 } 384 if err != nil { 385 return "", err 386 } 387 if pollable && useSetFileCompletionNotificationModes { 388 // We do not use events, so we can skip them always. 389 flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE) 390 // It's not safe to skip completion notifications for UDP: 391 // https://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx 392 if net == "tcp" { 393 flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 394 } 395 err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags) 396 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 { 397 fd.skipSyncNotif = true 398 } 399 } 400 // Disable SIO_UDP_CONNRESET behavior. 401 // http://support.microsoft.com/kb/263823 402 switch net { 403 case "udp", "udp4", "udp6": 404 ret := uint32(0) 405 flag := uint32(0) 406 size := uint32(unsafe.Sizeof(flag)) 407 err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0) 408 if err != nil { 409 return "wsaioctl", err 410 } 411 } 412 fd.rop.mode = 'r' 413 fd.wop.mode = 'w' 414 fd.rop.fd = fd 415 fd.wop.fd = fd 416 fd.rop.runtimeCtx = fd.pd.runtimeCtx 417 fd.wop.runtimeCtx = fd.pd.runtimeCtx 418 if !canCancelIO { 419 fd.rop.errc = make(chan error) 420 fd.wop.errc = make(chan error) 421 } 422 return "", nil 423 } 424 425 func (fd *FD) destroy() error { 426 if fd.Sysfd == syscall.InvalidHandle { 427 return syscall.EINVAL 428 } 429 // Poller may want to unregister fd in readiness notification mechanism, 430 // so this must be executed before fd.CloseFunc. 431 fd.pd.close() 432 var err error 433 if fd.isFile || fd.isConsole { 434 err = syscall.CloseHandle(fd.Sysfd) 435 } else if fd.isDir { 436 err = syscall.FindClose(fd.Sysfd) 437 } else { 438 // The net package uses the CloseFunc variable for testing. 439 err = CloseFunc(fd.Sysfd) 440 } 441 fd.Sysfd = syscall.InvalidHandle 442 runtime_Semrelease(&fd.csema) 443 return err 444 } 445 446 // Close closes the FD. The underlying file descriptor is closed by 447 // the destroy method when there are no remaining references. 448 func (fd *FD) Close() error { 449 if !fd.fdmu.increfAndClose() { 450 return errClosing(fd.isFile) 451 } 452 // unblock pending reader and writer 453 fd.pd.evict() 454 err := fd.decref() 455 // Wait until the descriptor is closed. If this was the only 456 // reference, it is already closed. 457 runtime_Semacquire(&fd.csema) 458 return err 459 } 460 461 // Shutdown wraps the shutdown network call. 462 func (fd *FD) Shutdown(how int) error { 463 if err := fd.incref(); err != nil { 464 return err 465 } 466 defer fd.decref() 467 return syscall.Shutdown(fd.Sysfd, how) 468 } 469 470 // Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length. 471 // This prevents us reading blocks larger than 4GB. 472 // See golang.org/issue/26923. 473 const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned 474 475 // Read implements io.Reader. 476 func (fd *FD) Read(buf []byte) (int, error) { 477 if err := fd.readLock(); err != nil { 478 return 0, err 479 } 480 defer fd.readUnlock() 481 482 if len(buf) > maxRW { 483 buf = buf[:maxRW] 484 } 485 486 var n int 487 var err error 488 if fd.isFile || fd.isDir || fd.isConsole { 489 fd.l.Lock() 490 defer fd.l.Unlock() 491 if fd.isConsole { 492 n, err = fd.readConsole(buf) 493 } else { 494 n, err = syscall.Read(fd.Sysfd, buf) 495 } 496 if err != nil { 497 n = 0 498 } 499 } else { 500 o := &fd.rop 501 o.InitBuf(buf) 502 n, err = rsrv.ExecIO(o, func(o *operation) error { 503 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 504 }) 505 if race.Enabled { 506 race.Acquire(unsafe.Pointer(&ioSync)) 507 } 508 } 509 if len(buf) != 0 { 510 err = fd.eofError(n, err) 511 } 512 return n, err 513 } 514 515 var ReadConsole = syscall.ReadConsole // changed for testing 516 517 // readConsole reads utf16 characters from console File, 518 // encodes them into utf8 and stores them in buffer b. 519 // It returns the number of utf8 bytes read and an error, if any. 520 func (fd *FD) readConsole(b []byte) (int, error) { 521 if len(b) == 0 { 522 return 0, nil 523 } 524 525 if fd.readuint16 == nil { 526 // Note: syscall.ReadConsole fails for very large buffers. 527 // The limit is somewhere around (but not exactly) 16384. 528 // Stay well below. 529 fd.readuint16 = make([]uint16, 0, 10000) 530 fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16)) 531 } 532 533 for fd.readbyteOffset >= len(fd.readbyte) { 534 n := cap(fd.readuint16) - len(fd.readuint16) 535 if n > len(b) { 536 n = len(b) 537 } 538 var nw uint32 539 err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil) 540 if err != nil { 541 return 0, err 542 } 543 uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)] 544 fd.readuint16 = fd.readuint16[:0] 545 buf := fd.readbyte[:0] 546 for i := 0; i < len(uint16s); i++ { 547 r := rune(uint16s[i]) 548 if utf16.IsSurrogate(r) { 549 if i+1 == len(uint16s) { 550 if nw > 0 { 551 // Save half surrogate pair for next time. 552 fd.readuint16 = fd.readuint16[:1] 553 fd.readuint16[0] = uint16(r) 554 break 555 } 556 r = utf8.RuneError 557 } else { 558 r = utf16.DecodeRune(r, rune(uint16s[i+1])) 559 if r != utf8.RuneError { 560 i++ 561 } 562 } 563 } 564 n := utf8.EncodeRune(buf[len(buf):cap(buf)], r) 565 buf = buf[:len(buf)+n] 566 } 567 fd.readbyte = buf 568 fd.readbyteOffset = 0 569 if nw == 0 { 570 break 571 } 572 } 573 574 src := fd.readbyte[fd.readbyteOffset:] 575 var i int 576 for i = 0; i < len(src) && i < len(b); i++ { 577 x := src[i] 578 if x == 0x1A { // Ctrl-Z 579 if i == 0 { 580 fd.readbyteOffset++ 581 } 582 break 583 } 584 b[i] = x 585 } 586 fd.readbyteOffset += i 587 return i, nil 588 } 589 590 // Pread emulates the Unix pread system call. 591 func (fd *FD) Pread(b []byte, off int64) (int, error) { 592 // Call incref, not readLock, because since pread specifies the 593 // offset it is independent from other reads. 594 if err := fd.incref(); err != nil { 595 return 0, err 596 } 597 defer fd.decref() 598 599 if len(b) > maxRW { 600 b = b[:maxRW] 601 } 602 603 fd.l.Lock() 604 defer fd.l.Unlock() 605 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 606 if e != nil { 607 return 0, e 608 } 609 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 610 o := syscall.Overlapped{ 611 OffsetHigh: uint32(off >> 32), 612 Offset: uint32(off), 613 } 614 var done uint32 615 e = syscall.ReadFile(fd.Sysfd, b, &done, &o) 616 if e != nil { 617 done = 0 618 if e == syscall.ERROR_HANDLE_EOF { 619 e = io.EOF 620 } 621 } 622 if len(b) != 0 { 623 e = fd.eofError(int(done), e) 624 } 625 return int(done), e 626 } 627 628 // ReadFrom wraps the recvfrom network call. 629 func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { 630 if len(buf) == 0 { 631 return 0, nil, nil 632 } 633 if len(buf) > maxRW { 634 buf = buf[:maxRW] 635 } 636 if err := fd.readLock(); err != nil { 637 return 0, nil, err 638 } 639 defer fd.readUnlock() 640 o := &fd.rop 641 o.InitBuf(buf) 642 n, err := rsrv.ExecIO(o, func(o *operation) error { 643 if o.rsa == nil { 644 o.rsa = new(syscall.RawSockaddrAny) 645 } 646 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 647 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 648 }) 649 err = fd.eofError(n, err) 650 if err != nil { 651 return n, nil, err 652 } 653 sa, _ := o.rsa.Sockaddr() 654 return n, sa, nil 655 } 656 657 // Write implements io.Writer. 658 func (fd *FD) Write(buf []byte) (int, error) { 659 if err := fd.writeLock(); err != nil { 660 return 0, err 661 } 662 defer fd.writeUnlock() 663 if fd.isFile || fd.isDir || fd.isConsole { 664 fd.l.Lock() 665 defer fd.l.Unlock() 666 } 667 668 ntotal := 0 669 for len(buf) > 0 { 670 b := buf 671 if len(b) > maxRW { 672 b = b[:maxRW] 673 } 674 var n int 675 var err error 676 if fd.isFile || fd.isDir || fd.isConsole { 677 if fd.isConsole { 678 n, err = fd.writeConsole(b) 679 } else { 680 n, err = syscall.Write(fd.Sysfd, b) 681 } 682 if err != nil { 683 n = 0 684 } 685 } else { 686 if race.Enabled { 687 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 688 } 689 o := &fd.wop 690 o.InitBuf(b) 691 n, err = wsrv.ExecIO(o, func(o *operation) error { 692 return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 693 }) 694 } 695 ntotal += n 696 if err != nil { 697 return ntotal, err 698 } 699 buf = buf[n:] 700 } 701 return ntotal, nil 702 } 703 704 // writeConsole writes len(b) bytes to the console File. 705 // It returns the number of bytes written and an error, if any. 706 func (fd *FD) writeConsole(b []byte) (int, error) { 707 n := len(b) 708 runes := make([]rune, 0, 256) 709 if len(fd.lastbits) > 0 { 710 b = append(fd.lastbits, b...) 711 fd.lastbits = nil 712 713 } 714 for len(b) >= utf8.UTFMax || utf8.FullRune(b) { 715 r, l := utf8.DecodeRune(b) 716 runes = append(runes, r) 717 b = b[l:] 718 } 719 if len(b) > 0 { 720 fd.lastbits = make([]byte, len(b)) 721 copy(fd.lastbits, b) 722 } 723 // syscall.WriteConsole seems to fail, if given large buffer. 724 // So limit the buffer to 16000 characters. This number was 725 // discovered by experimenting with syscall.WriteConsole. 726 const maxWrite = 16000 727 for len(runes) > 0 { 728 m := len(runes) 729 if m > maxWrite { 730 m = maxWrite 731 } 732 chunk := runes[:m] 733 runes = runes[m:] 734 uint16s := utf16.Encode(chunk) 735 for len(uint16s) > 0 { 736 var written uint32 737 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil) 738 if err != nil { 739 return 0, err 740 } 741 uint16s = uint16s[written:] 742 } 743 } 744 return n, nil 745 } 746 747 // Pwrite emulates the Unix pwrite system call. 748 func (fd *FD) Pwrite(buf []byte, off int64) (int, error) { 749 // Call incref, not writeLock, because since pwrite specifies the 750 // offset it is independent from other writes. 751 if err := fd.incref(); err != nil { 752 return 0, err 753 } 754 defer fd.decref() 755 756 fd.l.Lock() 757 defer fd.l.Unlock() 758 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 759 if e != nil { 760 return 0, e 761 } 762 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 763 764 ntotal := 0 765 for len(buf) > 0 { 766 b := buf 767 if len(b) > maxRW { 768 b = b[:maxRW] 769 } 770 var n uint32 771 o := syscall.Overlapped{ 772 OffsetHigh: uint32(off >> 32), 773 Offset: uint32(off), 774 } 775 e = syscall.WriteFile(fd.Sysfd, b, &n, &o) 776 ntotal += int(n) 777 if e != nil { 778 return ntotal, e 779 } 780 buf = buf[n:] 781 off += int64(n) 782 } 783 return ntotal, nil 784 } 785 786 // Writev emulates the Unix writev system call. 787 func (fd *FD) Writev(buf *[][]byte) (int64, error) { 788 if len(*buf) == 0 { 789 return 0, nil 790 } 791 if err := fd.writeLock(); err != nil { 792 return 0, err 793 } 794 defer fd.writeUnlock() 795 if race.Enabled { 796 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 797 } 798 o := &fd.wop 799 o.InitBufs(buf) 800 n, err := wsrv.ExecIO(o, func(o *operation) error { 801 return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(o.bufs)), &o.qty, 0, &o.o, nil) 802 }) 803 o.ClearBufs() 804 TestHookDidWritev(n) 805 consume(buf, int64(n)) 806 return int64(n), err 807 } 808 809 // WriteTo wraps the sendto network call. 810 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 811 if err := fd.writeLock(); err != nil { 812 return 0, err 813 } 814 defer fd.writeUnlock() 815 816 if len(buf) == 0 { 817 // handle zero-byte payload 818 o := &fd.wop 819 o.InitBuf(buf) 820 o.sa = sa 821 n, err := wsrv.ExecIO(o, func(o *operation) error { 822 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 823 }) 824 return n, err 825 } 826 827 ntotal := 0 828 for len(buf) > 0 { 829 b := buf 830 if len(b) > maxRW { 831 b = b[:maxRW] 832 } 833 o := &fd.wop 834 o.InitBuf(b) 835 o.sa = sa 836 n, err := wsrv.ExecIO(o, func(o *operation) error { 837 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 838 }) 839 ntotal += int(n) 840 if err != nil { 841 return ntotal, err 842 } 843 buf = buf[n:] 844 } 845 return ntotal, nil 846 } 847 848 // Call ConnectEx. This doesn't need any locking, since it is only 849 // called when the descriptor is first created. This is here rather 850 // than in the net package so that it can use fd.wop. 851 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error { 852 o := &fd.wop 853 o.sa = ra 854 _, err := wsrv.ExecIO(o, func(o *operation) error { 855 return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o) 856 }) 857 return err 858 } 859 860 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) { 861 // Submit accept request. 862 o.handle = s 863 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 864 _, err := rsrv.ExecIO(o, func(o *operation) error { 865 return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 866 }) 867 if err != nil { 868 CloseFunc(s) 869 return "acceptex", err 870 } 871 872 // Inherit properties of the listening socket. 873 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd))) 874 if err != nil { 875 CloseFunc(s) 876 return "setsockopt", err 877 } 878 879 return "", nil 880 } 881 882 // Accept handles accepting a socket. The sysSocket parameter is used 883 // to allocate the net socket. 884 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) { 885 if err := fd.readLock(); err != nil { 886 return syscall.InvalidHandle, nil, 0, "", err 887 } 888 defer fd.readUnlock() 889 890 o := &fd.rop 891 var rawsa [2]syscall.RawSockaddrAny 892 for { 893 s, err := sysSocket() 894 if err != nil { 895 return syscall.InvalidHandle, nil, 0, "", err 896 } 897 898 errcall, err := fd.acceptOne(s, rawsa[:], o) 899 if err == nil { 900 return s, rawsa[:], uint32(o.rsan), "", nil 901 } 902 903 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 904 // returned here. These happen if connection reset is received 905 // before AcceptEx could complete. These errors relate to new 906 // connection, not to AcceptEx, so ignore broken connection and 907 // try AcceptEx again for more connections. 908 errno, ok := err.(syscall.Errno) 909 if !ok { 910 return syscall.InvalidHandle, nil, 0, errcall, err 911 } 912 switch errno { 913 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 914 // ignore these and try again 915 default: 916 return syscall.InvalidHandle, nil, 0, errcall, err 917 } 918 } 919 } 920 921 // Seek wraps syscall.Seek. 922 func (fd *FD) Seek(offset int64, whence int) (int64, error) { 923 if err := fd.incref(); err != nil { 924 return 0, err 925 } 926 defer fd.decref() 927 928 fd.l.Lock() 929 defer fd.l.Unlock() 930 931 return syscall.Seek(fd.Sysfd, offset, whence) 932 } 933 934 // FindNextFile wraps syscall.FindNextFile. 935 func (fd *FD) FindNextFile(data *syscall.Win32finddata) error { 936 if err := fd.incref(); err != nil { 937 return err 938 } 939 defer fd.decref() 940 return syscall.FindNextFile(fd.Sysfd, data) 941 } 942 943 // Fchdir wraps syscall.Fchdir. 944 func (fd *FD) Fchdir() error { 945 if err := fd.incref(); err != nil { 946 return err 947 } 948 defer fd.decref() 949 return syscall.Fchdir(fd.Sysfd) 950 } 951 952 // GetFileType wraps syscall.GetFileType. 953 func (fd *FD) GetFileType() (uint32, error) { 954 if err := fd.incref(); err != nil { 955 return 0, err 956 } 957 defer fd.decref() 958 return syscall.GetFileType(fd.Sysfd) 959 } 960 961 // GetFileInformationByHandle wraps GetFileInformationByHandle. 962 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error { 963 if err := fd.incref(); err != nil { 964 return err 965 } 966 defer fd.decref() 967 return syscall.GetFileInformationByHandle(fd.Sysfd, data) 968 } 969 970 // RawControl invokes the user-defined function f for a non-IO 971 // operation. 972 func (fd *FD) RawControl(f func(uintptr)) error { 973 if err := fd.incref(); err != nil { 974 return err 975 } 976 defer fd.decref() 977 f(uintptr(fd.Sysfd)) 978 return nil 979 } 980 981 // RawRead invokes the user-defined function f for a read operation. 982 func (fd *FD) RawRead(f func(uintptr) bool) error { 983 if err := fd.readLock(); err != nil { 984 return err 985 } 986 defer fd.readUnlock() 987 for { 988 if f(uintptr(fd.Sysfd)) { 989 return nil 990 } 991 992 // Use a zero-byte read as a way to get notified when this 993 // socket is readable. h/t https://stackoverflow.com/a/42019668/332798 994 o := &fd.rop 995 o.InitBuf(nil) 996 if !fd.IsStream { 997 o.flags |= windows.MSG_PEEK 998 } 999 _, err := rsrv.ExecIO(o, func(o *operation) error { 1000 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 1001 }) 1002 if err == windows.WSAEMSGSIZE { 1003 // expected with a 0-byte peek, ignore. 1004 } else if err != nil { 1005 return err 1006 } 1007 } 1008 } 1009 1010 // RawWrite invokes the user-defined function f for a write operation. 1011 func (fd *FD) RawWrite(f func(uintptr) bool) error { 1012 if err := fd.writeLock(); err != nil { 1013 return err 1014 } 1015 defer fd.writeUnlock() 1016 1017 if f(uintptr(fd.Sysfd)) { 1018 return nil 1019 } 1020 1021 // TODO(tmm1): find a way to detect socket writability 1022 return syscall.EWINDOWS 1023 } 1024 1025 func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { 1026 switch sa := sa.(type) { 1027 case *syscall.SockaddrInet4: 1028 var raw syscall.RawSockaddrInet4 1029 raw.Family = syscall.AF_INET 1030 p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 1031 p[0] = byte(sa.Port >> 8) 1032 p[1] = byte(sa.Port) 1033 for i := 0; i < len(sa.Addr); i++ { 1034 raw.Addr[i] = sa.Addr[i] 1035 } 1036 return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil 1037 case *syscall.SockaddrInet6: 1038 var raw syscall.RawSockaddrInet6 1039 raw.Family = syscall.AF_INET6 1040 p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 1041 p[0] = byte(sa.Port >> 8) 1042 p[1] = byte(sa.Port) 1043 raw.Scope_id = sa.ZoneId 1044 for i := 0; i < len(sa.Addr); i++ { 1045 raw.Addr[i] = sa.Addr[i] 1046 } 1047 return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil 1048 default: 1049 return nil, 0, syscall.EWINDOWS 1050 } 1051 } 1052 1053 // ReadMsg wraps the WSARecvMsg network call. 1054 func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) { 1055 if err := fd.readLock(); err != nil { 1056 return 0, 0, 0, nil, err 1057 } 1058 defer fd.readUnlock() 1059 1060 if len(p) > maxRW { 1061 p = p[:maxRW] 1062 } 1063 1064 o := &fd.rop 1065 o.InitMsg(p, oob) 1066 o.rsa = new(syscall.RawSockaddrAny) 1067 o.msg.Name = o.rsa 1068 o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) 1069 n, err := rsrv.ExecIO(o, func(o *operation) error { 1070 return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) 1071 }) 1072 err = fd.eofError(n, err) 1073 var sa syscall.Sockaddr 1074 if err == nil { 1075 sa, err = o.rsa.Sockaddr() 1076 } 1077 return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err 1078 } 1079 1080 // WriteMsg wraps the WSASendMsg network call. 1081 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { 1082 if len(p) > maxRW { 1083 return 0, 0, errors.New("packet is too large (only 1GB is allowed)") 1084 } 1085 1086 if err := fd.writeLock(); err != nil { 1087 return 0, 0, err 1088 } 1089 defer fd.writeUnlock() 1090 1091 o := &fd.wop 1092 o.InitMsg(p, oob) 1093 if sa != nil { 1094 rsa, len, err := sockaddrToRaw(sa) 1095 if err != nil { 1096 return 0, 0, err 1097 } 1098 o.msg.Name = (*syscall.RawSockaddrAny)(rsa) 1099 o.msg.Namelen = len 1100 } 1101 n, err := wsrv.ExecIO(o, func(o *operation) error { 1102 return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) 1103 }) 1104 return n, int(o.msg.Control.Len), err 1105 }