fd_windows.mx raw
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 "internal/syscall/windows"
11 "io"
12 "sync"
13 "sync/atomic"
14 "syscall"
15 "unicode/utf16"
16 "unicode/utf8"
17 "unsafe"
18 )
19
20 var (
21 initErr error
22 ioSync uint64
23 )
24
25 // This package uses the SetFileCompletionNotificationModes Windows
26 // API to skip calling GetQueuedCompletionStatus if an IO operation
27 // completes synchronously. There is a known bug where
28 // SetFileCompletionNotificationModes crashes on some systems (see
29 // https://support.microsoft.com/kb/2568167 for details).
30
31 var socketCanUseSetFileCompletionNotificationModes bool // determines is SetFileCompletionNotificationModes is present and sockets can safely use it
32
33 // checkSetFileCompletionNotificationModes verifies that
34 // SetFileCompletionNotificationModes Windows API is present
35 // on the system and is safe to use.
36 // See https://support.microsoft.com/kb/2568167 for details.
37 func checkSetFileCompletionNotificationModes() {
38 err := syscall.LoadSetFileCompletionNotificationModes()
39 if err != nil {
40 return
41 }
42 protos := [2]int32{syscall.IPPROTO_TCP, 0}
43 var buf [32]syscall.WSAProtocolInfo
44 len := uint32(unsafe.Sizeof(buf))
45 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
46 if err != nil {
47 return
48 }
49 for i := int32(0); i < n; i++ {
50 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
51 return
52 }
53 }
54 socketCanUseSetFileCompletionNotificationModes = true
55 }
56
57 // InitWSA initiates the use of the Winsock DLL by the current process.
58 // It is called from the net package at init time to avoid
59 // loading ws2_32.dll when net is not used.
60 var InitWSA = sync.OnceFunc(func() {
61 var d syscall.WSAData
62 e := syscall.WSAStartup(uint32(0x202), &d)
63 if e != nil {
64 initErr = e
65 }
66 checkSetFileCompletionNotificationModes()
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 relies on it.
73 o syscall.Overlapped
74
75 // fields used by runtime.netpoll
76 runtimeCtx uintptr
77 mode int32
78
79 // fields used only by net package
80 fd *FD
81 buf syscall.WSABuf
82 msg windows.WSAMsg
83 sa syscall.Sockaddr
84 rsa *syscall.RawSockaddrAny
85 rsan int32
86 handle syscall.Handle
87 flags uint32
88 qty uint32
89 bufs []syscall.WSABuf
90 }
91
92 func (o *operation) setEvent() {
93 h, err := windows.CreateEvent(nil, 0, 0, nil)
94 if err != nil {
95 // This shouldn't happen when all CreateEvent arguments are zero.
96 panic(err)
97 }
98 // Set the low bit so that the external IOCP doesn't receive the completion packet.
99 o.o.HEvent = h | 1
100 }
101
102 func (o *operation) close() {
103 if o.o.HEvent != 0 {
104 syscall.CloseHandle(o.o.HEvent)
105 }
106 }
107
108 func (o *operation) overlapped() *syscall.Overlapped {
109 if o.fd.isBlocking {
110 // Don't return the overlapped object if the file handle
111 // doesn't use overlapped I/O. It could be used, but
112 // that would then use the file pointer stored in the
113 // overlapped object rather than the real file pointer.
114 return nil
115 }
116 return &o.o
117 }
118
119 func (o *operation) InitBuf(buf []byte) {
120 o.buf.Len = uint32(len(buf))
121 o.buf.Buf = nil
122 if len(buf) != 0 {
123 o.buf.Buf = &buf[0]
124 }
125 }
126
127 func (o *operation) InitBufs(buf *[][]byte) {
128 if o.bufs == nil {
129 o.bufs = []syscall.WSABuf{:0:len(*buf)}
130 } else {
131 o.bufs = o.bufs[:0]
132 }
133 for _, b := range *buf {
134 if len(b) == 0 {
135 o.bufs = append(o.bufs, syscall.WSABuf{})
136 continue
137 }
138 for len(b) > maxRW {
139 o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
140 b = b[maxRW:]
141 }
142 if len(b) > 0 {
143 o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
144 }
145 }
146 }
147
148 // ClearBufs clears all pointers to Buffers parameter captured
149 // by InitBufs, so it can be released by garbage collector.
150 func (o *operation) ClearBufs() {
151 for i := range o.bufs {
152 o.bufs[i].Buf = nil
153 }
154 o.bufs = o.bufs[:0]
155 }
156
157 func (o *operation) InitMsg(p []byte, oob []byte) {
158 o.InitBuf(p)
159 o.msg.Buffers = &o.buf
160 o.msg.BufferCount = 1
161
162 o.msg.Name = nil
163 o.msg.Namelen = 0
164
165 o.msg.Flags = 0
166 o.msg.Control.Len = uint32(len(oob))
167 o.msg.Control.Buf = nil
168 if len(oob) != 0 {
169 o.msg.Control.Buf = &oob[0]
170 }
171 }
172
173 // waitIO waits for the IO operation o to complete.
174 func waitIO(o *operation) error {
175 if o.fd.isBlocking {
176 panic("can't wait on blocking operations")
177 }
178 fd := o.fd
179 if !fd.pollable() {
180 // The overlapped handle is not added to the runtime poller,
181 // the only way to wait for the IO to complete is block until
182 // the overlapped event is signaled.
183 _, err := syscall.WaitForSingleObject(o.o.HEvent, syscall.INFINITE)
184 return err
185 }
186 // Wait for our request to complete.
187 err := fd.pd.wait(int(o.mode), fd.isFile)
188 switch err {
189 case nil, ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
190 // No other error is expected.
191 default:
192 panic("unexpected runtime.netpoll error: " + err.Error())
193 }
194 return err
195 }
196
197 // cancelIO cancels the IO operation o and waits for it to complete.
198 func cancelIO(o *operation) {
199 fd := o.fd
200 if !fd.pollable() {
201 return
202 }
203 // Cancel our request.
204 err := syscall.CancelIoEx(fd.Sysfd, &o.o)
205 // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
206 if err != nil && err != syscall.ERROR_NOT_FOUND {
207 // TODO(brainman): maybe do something else, but panic.
208 panic(err)
209 }
210 fd.pd.waitCanceled(int(o.mode))
211 }
212
213 // execIO executes a single IO operation o.
214 // It supports both synchronous and asynchronous IO.
215 // o.qty and o.flags are set to zero before calling submit
216 // to avoid reusing the values from a previous call.
217 func execIO(o *operation, submit func(o *operation) error) (int, error) {
218 fd := o.fd
219 // Notify runtime netpoll about starting IO.
220 err := fd.pd.prepare(int(o.mode), fd.isFile)
221 if err != nil {
222 return 0, err
223 }
224 // Start IO.
225 if !fd.isBlocking && o.o.HEvent == 0 && !fd.pollable() {
226 // If the handle is opened for overlapped IO but we can't
227 // use the runtime poller, then we need to use an
228 // event to wait for the IO to complete.
229 o.setEvent()
230 }
231 o.qty = 0
232 o.flags = 0
233 err = submit(o)
234 var waitErr error
235 // Blocking operations shouldn't return ERROR_IO_PENDING.
236 // Continue without waiting if that happens.
237 if !o.fd.isBlocking && (err == syscall.ERROR_IO_PENDING || (err == nil && !o.fd.skipSyncNotif)) {
238 // IO started asynchronously or completed synchronously but
239 // a sync notification is required. Wait for it to complete.
240 waitErr = waitIO(o)
241 if waitErr != nil {
242 // IO interrupted by "close" or "timeout".
243 cancelIO(o)
244 // We issued a cancellation request, but the IO operation may still succeeded
245 // before the cancellation request runs.
246 }
247 if fd.isFile {
248 err = windows.GetOverlappedResult(fd.Sysfd, &o.o, &o.qty, false)
249 } else {
250 err = windows.WSAGetOverlappedResult(fd.Sysfd, &o.o, &o.qty, false, &o.flags)
251 }
252 }
253 switch err {
254 case syscall.ERROR_OPERATION_ABORTED:
255 // ERROR_OPERATION_ABORTED may have been caused by us. In that case,
256 // map it to our own error. Don't do more than that, each submitted
257 // function may have its own meaning for each error.
258 if waitErr != nil {
259 // IO canceled by the poller while waiting for completion.
260 err = waitErr
261 } else if fd.kind == kindPipe && fd.closing() {
262 // Close uses CancelIoEx to interrupt concurrent I/O for pipes.
263 // If the fd is a pipe and the Write was interrupted by CancelIoEx,
264 // we assume it is interrupted by Close.
265 err = errClosing(fd.isFile)
266 }
267 case windows.ERROR_IO_INCOMPLETE:
268 // waitIO couldn't wait for the IO to complete.
269 if waitErr != nil {
270 // The wait error will be more informative.
271 err = waitErr
272 }
273 }
274 return int(o.qty), err
275 }
276
277 // FD is a file descriptor. The net and os packages embed this type in
278 // a larger type representing a network connection or OS file.
279 type FD struct {
280 // Lock sysfd and serialize access to Read and Write methods.
281 fdmu fdMutex
282
283 // System file descriptor. Immutable until Close.
284 Sysfd syscall.Handle
285
286 // Read operation.
287 rop operation
288 // Write operation.
289 wop operation
290
291 // I/O poller.
292 pd pollDesc
293
294 // Used to implement pread/pwrite.
295 l sync.Mutex
296
297 // The file offset for the next read or write.
298 // Overlapped IO operations don't use the real file pointer,
299 // so we need to keep track of the offset ourselves.
300 offset int64
301
302 // For console I/O.
303 lastbits []byte // first few bytes of the last incomplete rune in last write
304 readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
305 readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
306 readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read
307
308 // Semaphore signaled when file is closed.
309 csema uint32
310
311 skipSyncNotif bool
312
313 // Whether this is a streaming descriptor, as opposed to a
314 // packet-based descriptor like a UDP socket.
315 IsStream bool
316
317 // Whether a zero byte read indicates EOF. This is false for a
318 // message based socket connection.
319 ZeroReadIsEOF bool
320
321 // Whether the handle is owned by os.File.
322 isFile bool
323
324 // The kind of this file.
325 kind fileKind
326
327 // Whether FILE_FLAG_OVERLAPPED was not set when opening the file.
328 isBlocking bool
329
330 disassociated atomic.Bool
331 }
332
333 // setOffset sets the offset fields of the overlapped object
334 // to the given offset. The fd.l lock must be held.
335 //
336 // Overlapped IO operations don't update the offset fields
337 // of the overlapped object nor the file pointer automatically,
338 // so we do that manually here.
339 // Note that this is a best effort that only works if the file
340 // pointer is completely owned by this operation. We could
341 // call seek to allow other processes or other operations on the
342 // same file to see the updated offset. That would be inefficient
343 // and won't work for concurrent operations anyway. If concurrent
344 // operations are needed, then the caller should serialize them
345 // using an external mechanism.
346 func (fd *FD) setOffset(off int64) {
347 fd.offset = off
348 fd.rop.o.OffsetHigh, fd.rop.o.Offset = uint32(off>>32), uint32(off)
349 fd.wop.o.OffsetHigh, fd.wop.o.Offset = uint32(off>>32), uint32(off)
350 }
351
352 // addOffset adds the given offset to the current offset.
353 func (fd *FD) addOffset(off int) {
354 fd.setOffset(fd.offset + int64(off))
355 }
356
357 // pollable should be used instead of fd.pd.pollable(),
358 // as it is aware of the disassociated state.
359 func (fd *FD) pollable() bool {
360 return fd.pd.pollable() && !fd.disassociated.Load()
361 }
362
363 // fileKind describes the kind of file.
364 type fileKind byte
365
366 const (
367 kindNet fileKind = iota
368 kindFile
369 kindConsole
370 kindPipe
371 kindFileNet
372 )
373
374 // Init initializes the FD. The Sysfd field should already be set.
375 // This can be called multiple times on a single FD.
376 // The net argument is a network name from the net package (e.g., "tcp"),
377 // or "file" or "console" or "dir".
378 // Set pollable to true if fd should be managed by runtime netpoll.
379 // Pollable must be set to true for overlapped fds.
380 func (fd *FD) Init(net []byte, pollable bool) error {
381 if initErr != nil {
382 return initErr
383 }
384
385 switch net {
386 case "file":
387 fd.kind = kindFile
388 case "console":
389 fd.kind = kindConsole
390 case "pipe":
391 fd.kind = kindPipe
392 case "file+net":
393 fd.kind = kindFileNet
394 default:
395 // We don't actually care about the various network types.
396 fd.kind = kindNet
397 }
398 fd.isFile = fd.kind != kindNet
399 fd.isBlocking = !pollable
400 fd.rop.mode = 'r'
401 fd.wop.mode = 'w'
402 fd.rop.fd = fd
403 fd.wop.fd = fd
404
405 // It is safe to add overlapped handles that also perform I/O
406 // outside of the runtime poller. The runtime poller will ignore
407 // I/O completion notifications not initiated by us.
408 err := fd.pd.init(fd)
409 if err != nil {
410 return err
411 }
412 fd.rop.runtimeCtx = fd.pd.runtimeCtx
413 fd.wop.runtimeCtx = fd.pd.runtimeCtx
414 if fd.kind != kindNet || socketCanUseSetFileCompletionNotificationModes {
415 // Non-socket handles can use SetFileCompletionNotificationModes without problems.
416 err := syscall.SetFileCompletionNotificationModes(fd.Sysfd,
417 syscall.FILE_SKIP_SET_EVENT_ON_HANDLE|syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,
418 )
419 fd.skipSyncNotif = err == nil
420 }
421 return nil
422 }
423
424 // DisassociateIOCP disassociates the file handle from the IOCP.
425 // The disassociate operation will not succeed if there is any
426 // in-progress IO operation on the file handle.
427 func (fd *FD) DisassociateIOCP() error {
428 if err := fd.incref(); err != nil {
429 return err
430 }
431 defer fd.decref()
432
433 if fd.isBlocking || !fd.pollable() {
434 // Nothing to disassociate.
435 return nil
436 }
437
438 info := windows.FILE_COMPLETION_INFORMATION{}
439 if err := windows.NtSetInformationFile(fd.Sysfd, &windows.IO_STATUS_BLOCK{}, unsafe.Pointer(&info), uint32(unsafe.Sizeof(info)), windows.FileReplaceCompletionInformation); err != nil {
440 return err
441 }
442 fd.disassociated.Store(true)
443 // Don't call fd.pd.close(), it would be too racy.
444 // There is no harm on leaving fd.pd open until Close is called.
445 return nil
446 }
447
448 func (fd *FD) destroy() error {
449 if fd.Sysfd == syscall.InvalidHandle {
450 return syscall.EINVAL
451 }
452 fd.rop.close()
453 fd.wop.close()
454 // Poller may want to unregister fd in readiness notification mechanism,
455 // so this must be executed before fd.CloseFunc.
456 fd.pd.close()
457 var err error
458 switch fd.kind {
459 case kindNet, kindFileNet:
460 // The net package uses the CloseFunc variable for testing.
461 err = CloseFunc(fd.Sysfd)
462 default:
463 err = syscall.CloseHandle(fd.Sysfd)
464 }
465 fd.Sysfd = syscall.InvalidHandle
466 runtime_Semrelease(&fd.csema)
467 return err
468 }
469
470 // Close closes the FD. The underlying file descriptor is closed by
471 // the destroy method when there are no remaining references.
472 func (fd *FD) Close() error {
473 if !fd.fdmu.increfAndClose() {
474 return errClosing(fd.isFile)
475 }
476
477 if fd.kind == kindPipe {
478 syscall.CancelIoEx(fd.Sysfd, nil)
479 }
480 // unblock pending reader and writer
481 fd.pd.evict()
482 err := fd.decref()
483 // Wait until the descriptor is closed. If this was the only
484 // reference, it is already closed.
485 runtime_Semacquire(&fd.csema)
486 return err
487 }
488
489 // Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length.
490 // This prevents us reading blocks larger than 4GB.
491 // See golang.org/issue/26923.
492 const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
493
494 // Read implements io.Reader.
495 func (fd *FD) Read(buf []byte) (int, error) {
496 if err := fd.readLock(); err != nil {
497 return 0, err
498 }
499 defer fd.readUnlock()
500 if fd.kind == kindFile {
501 fd.l.Lock()
502 defer fd.l.Unlock()
503 }
504
505 if len(buf) > maxRW {
506 buf = buf[:maxRW]
507 }
508
509 var n int
510 var err error
511 switch fd.kind {
512 case kindConsole:
513 n, err = fd.readConsole(buf)
514 case kindFile, kindPipe:
515 o := &fd.rop
516 o.InitBuf(buf)
517 n, err = execIO(o, func(o *operation) error {
518 return syscall.ReadFile(o.fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &o.qty, o.overlapped())
519 })
520 fd.addOffset(n)
521 switch err {
522 case syscall.ERROR_HANDLE_EOF:
523 err = io.EOF
524 case syscall.ERROR_BROKEN_PIPE:
525 // ReadFile only documents ERROR_BROKEN_PIPE for pipes.
526 if fd.kind == kindPipe {
527 err = io.EOF
528 }
529 }
530 case kindNet:
531 o := &fd.rop
532 o.InitBuf(buf)
533 n, err = execIO(o, func(o *operation) error {
534 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
535 })
536 if race.Enabled {
537 race.Acquire(unsafe.Pointer(&ioSync))
538 }
539 }
540 if len(buf) != 0 {
541 err = fd.eofError(n, err)
542 }
543 return n, err
544 }
545
546 var ReadConsole = syscall.ReadConsole // changed for testing
547
548 // readConsole reads utf16 characters from console File,
549 // encodes them into utf8 and stores them in buffer b.
550 // It returns the number of utf8 bytes read and an error, if any.
551 func (fd *FD) readConsole(b []byte) (int, error) {
552 if len(b) == 0 {
553 return 0, nil
554 }
555
556 if fd.readuint16 == nil {
557 // Note: syscall.ReadConsole fails for very large buffers.
558 // The limit is somewhere around (but not exactly) 16384.
559 // Stay well below.
560 fd.readuint16 = []uint16{:0:10000}
561 fd.readbyte = []byte{:0:4*cap(fd.readuint16)}
562 }
563
564 for fd.readbyteOffset >= len(fd.readbyte) {
565 n := cap(fd.readuint16) - len(fd.readuint16)
566 if n > len(b) {
567 n = len(b)
568 }
569 var nw uint32
570 err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
571 if err != nil {
572 return 0, err
573 }
574 uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
575 fd.readuint16 = fd.readuint16[:0]
576 buf := fd.readbyte[:0]
577 for i := 0; i < len(uint16s); i++ {
578 r := rune(uint16s[i])
579 if utf16.IsSurrogate(r) {
580 if i+1 == len(uint16s) {
581 if nw > 0 {
582 // Save half surrogate pair for next time.
583 fd.readuint16 = fd.readuint16[:1]
584 fd.readuint16[0] = uint16(r)
585 break
586 }
587 r = utf8.RuneError
588 } else {
589 r = utf16.DecodeRune(r, rune(uint16s[i+1]))
590 if r != utf8.RuneError {
591 i++
592 }
593 }
594 }
595 buf = utf8.AppendRune(buf, r)
596 }
597 fd.readbyte = buf
598 fd.readbyteOffset = 0
599 if nw == 0 {
600 break
601 }
602 }
603
604 src := fd.readbyte[fd.readbyteOffset:]
605 var i int
606 for i = 0; i < len(src) && i < len(b); i++ {
607 x := src[i]
608 if x == 0x1A { // Ctrl-Z
609 if i == 0 {
610 fd.readbyteOffset++
611 }
612 break
613 }
614 b[i] = x
615 }
616 fd.readbyteOffset += i
617 return i, nil
618 }
619
620 // Pread emulates the Unix pread system call.
621 func (fd *FD) Pread(b []byte, off int64) (int, error) {
622 if fd.kind == kindPipe {
623 // Pread does not work with pipes
624 return 0, syscall.ESPIPE
625 }
626 // Call incref, not readLock, because since pread specifies the
627 // offset it is independent from other reads.
628 if err := fd.incref(); err != nil {
629 return 0, err
630 }
631 defer fd.decref()
632
633 if len(b) > maxRW {
634 b = b[:maxRW]
635 }
636
637 fd.l.Lock()
638 defer fd.l.Unlock()
639 if fd.isBlocking {
640 curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
641 if err != nil {
642 return 0, err
643 }
644 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
645 defer fd.setOffset(curoffset)
646 } else {
647 // Overlapped handles don't have the file pointer updated
648 // when performing I/O operations, so there is no need to
649 // call Seek to reset the file pointer.
650 // Also, some overlapped file handles don't support seeking.
651 // See https://go.dev/issues/74951.
652 curoffset := fd.offset
653 defer fd.setOffset(curoffset)
654 }
655 o := &fd.rop
656 o.InitBuf(b)
657 fd.setOffset(off)
658 n, err := execIO(o, func(o *operation) error {
659 return syscall.ReadFile(o.fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &o.qty, &o.o)
660 })
661 if err == syscall.ERROR_HANDLE_EOF {
662 err = io.EOF
663 }
664 if len(b) != 0 {
665 err = fd.eofError(n, err)
666 }
667 return n, err
668 }
669
670 // ReadFrom wraps the recvfrom network call.
671 func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
672 if len(buf) == 0 {
673 return 0, nil, nil
674 }
675 if len(buf) > maxRW {
676 buf = buf[:maxRW]
677 }
678 if err := fd.readLock(); err != nil {
679 return 0, nil, err
680 }
681 defer fd.readUnlock()
682 o := &fd.rop
683 o.InitBuf(buf)
684 n, err := execIO(o, func(o *operation) error {
685 if o.rsa == nil {
686 o.rsa = &syscall.RawSockaddrAny{}
687 }
688 o.rsan = int32(unsafe.Sizeof(*o.rsa))
689 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
690 })
691 err = fd.eofError(n, err)
692 if err != nil {
693 return n, nil, err
694 }
695 sa, _ := o.rsa.Sockaddr()
696 return n, sa, nil
697 }
698
699 // ReadFromInet4 wraps the recvfrom network call for IPv4.
700 func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
701 if len(buf) == 0 {
702 return 0, nil
703 }
704 if len(buf) > maxRW {
705 buf = buf[:maxRW]
706 }
707 if err := fd.readLock(); err != nil {
708 return 0, err
709 }
710 defer fd.readUnlock()
711 o := &fd.rop
712 o.InitBuf(buf)
713 n, err := execIO(o, func(o *operation) error {
714 if o.rsa == nil {
715 o.rsa = &syscall.RawSockaddrAny{}
716 }
717 o.rsan = int32(unsafe.Sizeof(*o.rsa))
718 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
719 })
720 err = fd.eofError(n, err)
721 if err != nil {
722 return n, err
723 }
724 rawToSockaddrInet4(o.rsa, sa4)
725 return n, err
726 }
727
728 // ReadFromInet6 wraps the recvfrom network call for IPv6.
729 func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
730 if len(buf) == 0 {
731 return 0, nil
732 }
733 if len(buf) > maxRW {
734 buf = buf[:maxRW]
735 }
736 if err := fd.readLock(); err != nil {
737 return 0, err
738 }
739 defer fd.readUnlock()
740 o := &fd.rop
741 o.InitBuf(buf)
742 n, err := execIO(o, func(o *operation) error {
743 if o.rsa == nil {
744 o.rsa = &syscall.RawSockaddrAny{}
745 }
746 o.rsan = int32(unsafe.Sizeof(*o.rsa))
747 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
748 })
749 err = fd.eofError(n, err)
750 if err != nil {
751 return n, err
752 }
753 rawToSockaddrInet6(o.rsa, sa6)
754 return n, err
755 }
756
757 // Write implements io.Writer.
758 func (fd *FD) Write(buf []byte) (int, error) {
759 if err := fd.writeLock(); err != nil {
760 return 0, err
761 }
762 defer fd.writeUnlock()
763 if fd.kind == kindFile {
764 fd.l.Lock()
765 defer fd.l.Unlock()
766 }
767
768 var ntotal int
769 for {
770 max := len(buf)
771 if max-ntotal > maxRW {
772 max = ntotal + maxRW
773 }
774 b := buf[ntotal:max]
775 var n int
776 var err error
777 switch fd.kind {
778 case kindConsole:
779 n, err = fd.writeConsole(b)
780 case kindPipe, kindFile:
781 o := &fd.wop
782 o.InitBuf(b)
783 n, err = execIO(o, func(o *operation) error {
784 return syscall.WriteFile(o.fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &o.qty, o.overlapped())
785 })
786 fd.addOffset(n)
787 case kindNet:
788 if race.Enabled {
789 race.ReleaseMerge(unsafe.Pointer(&ioSync))
790 }
791 o := &fd.wop
792 o.InitBuf(b)
793 n, err = execIO(o, func(o *operation) error {
794 return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
795 })
796 }
797 ntotal += n
798 if ntotal == len(buf) || err != nil {
799 return ntotal, err
800 }
801 if n == 0 {
802 return ntotal, io.ErrUnexpectedEOF
803 }
804 }
805 }
806
807 // writeConsole writes len(b) bytes to the console File.
808 // It returns the number of bytes written and an error, if any.
809 func (fd *FD) writeConsole(b []byte) (int, error) {
810 n := len(b)
811 runes := []rune{:0:256}
812 if len(fd.lastbits) > 0 {
813 b = append(fd.lastbits, b...)
814 fd.lastbits = nil
815
816 }
817 for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
818 r, l := utf8.DecodeRune(b)
819 runes = append(runes, r)
820 b = b[l:]
821 }
822 if len(b) > 0 {
823 fd.lastbits = []byte{:len(b)}
824 copy(fd.lastbits, b)
825 }
826 // syscall.WriteConsole seems to fail, if given large buffer.
827 // So limit the buffer to 16000 characters. This number was
828 // discovered by experimenting with syscall.WriteConsole.
829 const maxWrite = 16000
830 for len(runes) > 0 {
831 m := len(runes)
832 if m > maxWrite {
833 m = maxWrite
834 }
835 chunk := runes[:m]
836 runes = runes[m:]
837 uint16s := utf16.Encode(chunk)
838 for len(uint16s) > 0 {
839 var written uint32
840 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
841 if err != nil {
842 return 0, err
843 }
844 uint16s = uint16s[written:]
845 }
846 }
847 return n, nil
848 }
849
850 // Pwrite emulates the Unix pwrite system call.
851 func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
852 if fd.kind == kindPipe {
853 // Pwrite does not work with pipes
854 return 0, syscall.ESPIPE
855 }
856 // Call incref, not writeLock, because since pwrite specifies the
857 // offset it is independent from other writes.
858 if err := fd.incref(); err != nil {
859 return 0, err
860 }
861 defer fd.decref()
862
863 fd.l.Lock()
864 defer fd.l.Unlock()
865 if fd.isBlocking {
866 curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
867 if err != nil {
868 return 0, err
869 }
870 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
871 defer fd.setOffset(curoffset)
872 } else {
873 // Overlapped handles don't have the file pointer updated
874 // when performing I/O operations, so there is no need to
875 // call Seek to reset the file pointer.
876 // Also, some overlapped file handles don't support seeking.
877 // See https://go.dev/issues/74951.
878 curoffset := fd.offset
879 defer fd.setOffset(curoffset)
880 }
881
882 var ntotal int
883 for {
884 max := len(buf)
885 if max-ntotal > maxRW {
886 max = ntotal + maxRW
887 }
888 b := buf[ntotal:max]
889 o := &fd.wop
890 o.InitBuf(b)
891 fd.setOffset(off + int64(ntotal))
892 n, err := execIO(o, func(o *operation) error {
893 return syscall.WriteFile(o.fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &o.qty, &o.o)
894 })
895 if n > 0 {
896 ntotal += n
897 }
898 if ntotal == len(buf) || err != nil {
899 return ntotal, err
900 }
901 if n == 0 {
902 return ntotal, io.ErrUnexpectedEOF
903 }
904 }
905 }
906
907 // Writev emulates the Unix writev system call.
908 func (fd *FD) Writev(buf *[][]byte) (int64, error) {
909 if len(*buf) == 0 {
910 return 0, nil
911 }
912 if err := fd.writeLock(); err != nil {
913 return 0, err
914 }
915 defer fd.writeUnlock()
916 if race.Enabled {
917 race.ReleaseMerge(unsafe.Pointer(&ioSync))
918 }
919 o := &fd.wop
920 o.InitBufs(buf)
921 n, err := execIO(o, func(o *operation) error {
922 return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(o.bufs)), &o.qty, 0, &o.o, nil)
923 })
924 o.ClearBufs()
925 TestHookDidWritev(n)
926 consume(buf, int64(n))
927 return int64(n), err
928 }
929
930 // WriteTo wraps the sendto network call.
931 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
932 if err := fd.writeLock(); err != nil {
933 return 0, err
934 }
935 defer fd.writeUnlock()
936
937 if len(buf) == 0 {
938 // handle zero-byte payload
939 o := &fd.wop
940 o.InitBuf(buf)
941 o.sa = sa
942 n, err := execIO(o, func(o *operation) error {
943 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
944 })
945 return n, err
946 }
947
948 ntotal := 0
949 for len(buf) > 0 {
950 b := buf
951 if len(b) > maxRW {
952 b = b[:maxRW]
953 }
954 o := &fd.wop
955 o.InitBuf(b)
956 o.sa = sa
957 n, err := execIO(o, func(o *operation) error {
958 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
959 })
960 ntotal += int(n)
961 if err != nil {
962 return ntotal, err
963 }
964 buf = buf[n:]
965 }
966 return ntotal, nil
967 }
968
969 // WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4.
970 func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
971 if err := fd.writeLock(); err != nil {
972 return 0, err
973 }
974 defer fd.writeUnlock()
975
976 if len(buf) == 0 {
977 // handle zero-byte payload
978 o := &fd.wop
979 o.InitBuf(buf)
980 n, err := execIO(o, func(o *operation) error {
981 return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
982 })
983 return n, err
984 }
985
986 ntotal := 0
987 for len(buf) > 0 {
988 b := buf
989 if len(b) > maxRW {
990 b = b[:maxRW]
991 }
992 o := &fd.wop
993 o.InitBuf(b)
994 n, err := execIO(o, func(o *operation) error {
995 return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
996 })
997 ntotal += int(n)
998 if err != nil {
999 return ntotal, err
1000 }
1001 buf = buf[n:]
1002 }
1003 return ntotal, nil
1004 }
1005
1006 // WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6.
1007 func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
1008 if err := fd.writeLock(); err != nil {
1009 return 0, err
1010 }
1011 defer fd.writeUnlock()
1012
1013 if len(buf) == 0 {
1014 // handle zero-byte payload
1015 o := &fd.wop
1016 o.InitBuf(buf)
1017 n, err := execIO(o, func(o *operation) error {
1018 return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
1019 })
1020 return n, err
1021 }
1022
1023 ntotal := 0
1024 for len(buf) > 0 {
1025 b := buf
1026 if len(b) > maxRW {
1027 b = b[:maxRW]
1028 }
1029 o := &fd.wop
1030 o.InitBuf(b)
1031 n, err := execIO(o, func(o *operation) error {
1032 return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
1033 })
1034 ntotal += int(n)
1035 if err != nil {
1036 return ntotal, err
1037 }
1038 buf = buf[n:]
1039 }
1040 return ntotal, nil
1041 }
1042
1043 // Call ConnectEx. This doesn't need any locking, since it is only
1044 // called when the descriptor is first created. This is here rather
1045 // than in the net package so that it can use fd.wop.
1046 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
1047 o := &fd.wop
1048 o.sa = ra
1049 _, err := execIO(o, func(o *operation) error {
1050 return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o)
1051 })
1052 return err
1053 }
1054
1055 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) ([]byte, error) {
1056 // Submit accept request.
1057 o.handle = s
1058 o.rsan = int32(unsafe.Sizeof(rawsa[0]))
1059 _, err := execIO(o, func(o *operation) error {
1060 return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
1061 })
1062 if err != nil {
1063 CloseFunc(s)
1064 return "acceptex", err
1065 }
1066
1067 // Inherit properties of the listening socket.
1068 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
1069 if err != nil {
1070 CloseFunc(s)
1071 return "setsockopt", err
1072 }
1073
1074 return "", nil
1075 }
1076
1077 // Accept handles accepting a socket. The sysSocket parameter is used
1078 // to allocate the net socket.
1079 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, []byte, error) {
1080 if err := fd.readLock(); err != nil {
1081 return syscall.InvalidHandle, nil, 0, "", err
1082 }
1083 defer fd.readUnlock()
1084
1085 o := &fd.rop
1086 var rawsa [2]syscall.RawSockaddrAny
1087 for {
1088 s, err := sysSocket()
1089 if err != nil {
1090 return syscall.InvalidHandle, nil, 0, "", err
1091 }
1092
1093 errcall, err := fd.acceptOne(s, rawsa[:], o)
1094 if err == nil {
1095 return s, rawsa[:], uint32(o.rsan), "", nil
1096 }
1097
1098 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
1099 // returned here. These happen if connection reset is received
1100 // before AcceptEx could complete. These errors relate to new
1101 // connection, not to AcceptEx, so ignore broken connection and
1102 // try AcceptEx again for more connections.
1103 errno, ok := err.(syscall.Errno)
1104 if !ok {
1105 return syscall.InvalidHandle, nil, 0, errcall, err
1106 }
1107 switch errno {
1108 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
1109 // ignore these and try again
1110 default:
1111 return syscall.InvalidHandle, nil, 0, errcall, err
1112 }
1113 }
1114 }
1115
1116 // Seek wraps syscall.Seek.
1117 func (fd *FD) Seek(offset int64, whence int) (int64, error) {
1118 if fd.kind == kindPipe {
1119 return 0, syscall.ESPIPE
1120 }
1121 if err := fd.incref(); err != nil {
1122 return 0, err
1123 }
1124 defer fd.decref()
1125
1126 fd.l.Lock()
1127 defer fd.l.Unlock()
1128
1129 if !fd.isBlocking && whence == io.SeekCurrent {
1130 // Windows doesn't keep the file pointer for overlapped file handles.
1131 // We do it ourselves in case to account for any read or write
1132 // operations that may have occurred.
1133 offset += fd.offset
1134 }
1135 n, err := syscall.Seek(fd.Sysfd, offset, whence)
1136 fd.setOffset(n)
1137 return n, err
1138 }
1139
1140 // Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
1141 func (fd *FD) Fchmod(mode uint32) error {
1142 if err := fd.incref(); err != nil {
1143 return err
1144 }
1145 defer fd.decref()
1146
1147 var d syscall.ByHandleFileInformation
1148 if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
1149 return err
1150 }
1151 attrs := d.FileAttributes
1152 if mode&syscall.S_IWRITE != 0 {
1153 attrs &^= syscall.FILE_ATTRIBUTE_READONLY
1154 } else {
1155 attrs |= syscall.FILE_ATTRIBUTE_READONLY
1156 }
1157 if attrs == d.FileAttributes {
1158 return nil
1159 }
1160
1161 var du windows.FILE_BASIC_INFO
1162 du.FileAttributes = attrs
1163 return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du)))
1164 }
1165
1166 // Fchdir wraps syscall.Fchdir.
1167 func (fd *FD) Fchdir() error {
1168 if err := fd.incref(); err != nil {
1169 return err
1170 }
1171 defer fd.decref()
1172 return syscall.Fchdir(fd.Sysfd)
1173 }
1174
1175 // GetFileType wraps syscall.GetFileType.
1176 func (fd *FD) GetFileType() (uint32, error) {
1177 if err := fd.incref(); err != nil {
1178 return 0, err
1179 }
1180 defer fd.decref()
1181 return syscall.GetFileType(fd.Sysfd)
1182 }
1183
1184 // GetFileInformationByHandle wraps GetFileInformationByHandle.
1185 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
1186 if err := fd.incref(); err != nil {
1187 return err
1188 }
1189 defer fd.decref()
1190 return syscall.GetFileInformationByHandle(fd.Sysfd, data)
1191 }
1192
1193 // RawRead invokes the user-defined function f for a read operation.
1194 func (fd *FD) RawRead(f func(uintptr) bool) error {
1195 if err := fd.readLock(); err != nil {
1196 return err
1197 }
1198 defer fd.readUnlock()
1199 for {
1200 if f(uintptr(fd.Sysfd)) {
1201 return nil
1202 }
1203
1204 // Use a zero-byte read as a way to get notified when this
1205 // socket is readable. h/t https://stackoverflow.com/a/42019668/332798
1206 o := &fd.rop
1207 o.InitBuf(nil)
1208 _, err := execIO(o, func(o *operation) error {
1209 if !fd.IsStream {
1210 o.flags |= windows.MSG_PEEK
1211 }
1212 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
1213 })
1214 if err == windows.WSAEMSGSIZE {
1215 // expected with a 0-byte peek, ignore.
1216 } else if err != nil {
1217 return err
1218 }
1219 }
1220 }
1221
1222 // RawWrite invokes the user-defined function f for a write operation.
1223 func (fd *FD) RawWrite(f func(uintptr) bool) error {
1224 if err := fd.writeLock(); err != nil {
1225 return err
1226 }
1227 defer fd.writeUnlock()
1228
1229 if f(uintptr(fd.Sysfd)) {
1230 return nil
1231 }
1232
1233 // TODO(tmm1): find a way to detect socket writability
1234 return syscall.EWINDOWS
1235 }
1236
1237 func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 {
1238 *rsa = syscall.RawSockaddrAny{}
1239 raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
1240 raw.Family = syscall.AF_INET
1241 p := (*[2]byte)(unsafe.Pointer(&raw.Port))
1242 p[0] = byte(sa.Port >> 8)
1243 p[1] = byte(sa.Port)
1244 raw.Addr = sa.Addr
1245 return int32(unsafe.Sizeof(*raw))
1246 }
1247
1248 func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 {
1249 *rsa = syscall.RawSockaddrAny{}
1250 raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
1251 raw.Family = syscall.AF_INET6
1252 p := (*[2]byte)(unsafe.Pointer(&raw.Port))
1253 p[0] = byte(sa.Port >> 8)
1254 p[1] = byte(sa.Port)
1255 raw.Scope_id = sa.ZoneId
1256 raw.Addr = sa.Addr
1257 return int32(unsafe.Sizeof(*raw))
1258 }
1259
1260 func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
1261 pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
1262 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
1263 sa.Port = int(p[0])<<8 + int(p[1])
1264 sa.Addr = pp.Addr
1265 }
1266
1267 func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
1268 pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
1269 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
1270 sa.Port = int(p[0])<<8 + int(p[1])
1271 sa.ZoneId = pp.Scope_id
1272 sa.Addr = pp.Addr
1273 }
1274
1275 func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) {
1276 switch sa := sa.(type) {
1277 case *syscall.SockaddrInet4:
1278 sz := sockaddrInet4ToRaw(rsa, sa)
1279 return sz, nil
1280 case *syscall.SockaddrInet6:
1281 sz := sockaddrInet6ToRaw(rsa, sa)
1282 return sz, nil
1283 default:
1284 return 0, syscall.EWINDOWS
1285 }
1286 }
1287
1288 // ReadMsg wraps the WSARecvMsg network call.
1289 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
1290 if err := fd.readLock(); err != nil {
1291 return 0, 0, 0, nil, err
1292 }
1293 defer fd.readUnlock()
1294
1295 if len(p) > maxRW {
1296 p = p[:maxRW]
1297 }
1298
1299 o := &fd.rop
1300 o.InitMsg(p, oob)
1301 if o.rsa == nil {
1302 o.rsa = &syscall.RawSockaddrAny{}
1303 }
1304 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1305 o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
1306 o.msg.Flags = uint32(flags)
1307 n, err := execIO(o, func(o *operation) error {
1308 return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
1309 })
1310 err = fd.eofError(n, err)
1311 var sa syscall.Sockaddr
1312 if err == nil {
1313 sa, err = o.rsa.Sockaddr()
1314 }
1315 return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err
1316 }
1317
1318 // ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4.
1319 func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
1320 if err := fd.readLock(); err != nil {
1321 return 0, 0, 0, err
1322 }
1323 defer fd.readUnlock()
1324
1325 if len(p) > maxRW {
1326 p = p[:maxRW]
1327 }
1328
1329 o := &fd.rop
1330 o.InitMsg(p, oob)
1331 if o.rsa == nil {
1332 o.rsa = &syscall.RawSockaddrAny{}
1333 }
1334 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1335 o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
1336 o.msg.Flags = uint32(flags)
1337 n, err := execIO(o, func(o *operation) error {
1338 return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
1339 })
1340 err = fd.eofError(n, err)
1341 if err == nil {
1342 rawToSockaddrInet4(o.rsa, sa4)
1343 }
1344 return n, int(o.msg.Control.Len), int(o.msg.Flags), err
1345 }
1346
1347 // ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6.
1348 func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
1349 if err := fd.readLock(); err != nil {
1350 return 0, 0, 0, err
1351 }
1352 defer fd.readUnlock()
1353
1354 if len(p) > maxRW {
1355 p = p[:maxRW]
1356 }
1357
1358 o := &fd.rop
1359 o.InitMsg(p, oob)
1360 if o.rsa == nil {
1361 o.rsa = &syscall.RawSockaddrAny{}
1362 }
1363 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1364 o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
1365 o.msg.Flags = uint32(flags)
1366 n, err := execIO(o, func(o *operation) error {
1367 return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
1368 })
1369 err = fd.eofError(n, err)
1370 if err == nil {
1371 rawToSockaddrInet6(o.rsa, sa6)
1372 }
1373 return n, int(o.msg.Control.Len), int(o.msg.Flags), err
1374 }
1375
1376 // WriteMsg wraps the WSASendMsg network call.
1377 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
1378 if len(p) > maxRW {
1379 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1380 }
1381
1382 if err := fd.writeLock(); err != nil {
1383 return 0, 0, err
1384 }
1385 defer fd.writeUnlock()
1386
1387 o := &fd.wop
1388 o.InitMsg(p, oob)
1389 if sa != nil {
1390 if o.rsa == nil {
1391 o.rsa = &syscall.RawSockaddrAny{}
1392 }
1393 len, err := sockaddrToRaw(o.rsa, sa)
1394 if err != nil {
1395 return 0, 0, err
1396 }
1397 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1398 o.msg.Namelen = len
1399 }
1400 n, err := execIO(o, func(o *operation) error {
1401 return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
1402 })
1403 return n, int(o.msg.Control.Len), err
1404 }
1405
1406 // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
1407 func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
1408 if len(p) > maxRW {
1409 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1410 }
1411
1412 if err := fd.writeLock(); err != nil {
1413 return 0, 0, err
1414 }
1415 defer fd.writeUnlock()
1416
1417 o := &fd.wop
1418 o.InitMsg(p, oob)
1419 if o.rsa == nil {
1420 o.rsa = &syscall.RawSockaddrAny{}
1421 }
1422 len := sockaddrInet4ToRaw(o.rsa, sa)
1423 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1424 o.msg.Namelen = len
1425 n, err := execIO(o, func(o *operation) error {
1426 return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
1427 })
1428 return n, int(o.msg.Control.Len), err
1429 }
1430
1431 // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
1432 func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
1433 if len(p) > maxRW {
1434 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1435 }
1436
1437 if err := fd.writeLock(); err != nil {
1438 return 0, 0, err
1439 }
1440 defer fd.writeUnlock()
1441
1442 o := &fd.wop
1443 o.InitMsg(p, oob)
1444 if o.rsa == nil {
1445 o.rsa = &syscall.RawSockaddrAny{}
1446 }
1447 len := sockaddrInet6ToRaw(o.rsa, sa)
1448 o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
1449 o.msg.Namelen = len
1450 n, err := execIO(o, func(o *operation) error {
1451 return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
1452 })
1453 return n, int(o.msg.Control.Len), err
1454 }
1455
1456 func DupCloseOnExec(fd int) (int, []byte, error) {
1457 proc, err := syscall.GetCurrentProcess()
1458 if err != nil {
1459 return 0, "GetCurrentProcess", err
1460 }
1461
1462 var nfd syscall.Handle
1463 const inherit = false // analogous to CLOEXEC
1464 if err := syscall.DuplicateHandle(proc, syscall.Handle(fd), proc, &nfd, 0, inherit, syscall.DUPLICATE_SAME_ACCESS); err != nil {
1465 return 0, "DuplicateHandle", err
1466 }
1467 return int(nfd), "", nil
1468 }
1469