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