RecvMsg implements socket.Socket.RecvMsg.
(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64)
| 615 | |
| 616 | // RecvMsg implements socket.Socket.RecvMsg. |
| 617 | func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64) (int, int, linux.SockAddr, uint32, socket.ControlMessages, *syserr.Error) { |
| 618 | var addr, control []byte |
| 619 | if senderRequested { |
| 620 | if s.skType != linux.SOCK_STREAM { |
| 621 | addr = make([]byte, sizeofSockaddr) |
| 622 | } else { |
| 623 | // According to UNIX98, msg_name/msg_namelen are ignored on connected socket. |
| 624 | senderRequested = false |
| 625 | } |
| 626 | } |
| 627 | if controlDataLen > 0 { |
| 628 | control = make([]byte, controlDataLen) |
| 629 | } |
| 630 | |
| 631 | // Store nonblock info from original flag. |
| 632 | nonblock := flags&syscall.MSG_DONTWAIT != 0 |
| 633 | waitall := !nonblock && flags&syscall.MSG_WAITALL != 0 |
| 634 | |
| 635 | var mflag int |
| 636 | var n int64 |
| 637 | var err error |
| 638 | // Always set as non-blocking for recv. |
| 639 | sysflags := flags | syscall.MSG_DONTWAIT |
| 640 | n, addr, control, mflag, err = s.recv(t, dst, sysflags, addr, control) |
| 641 | |
| 642 | var senderAddr linux.SockAddr |
| 643 | var addrlen uint32 |
| 644 | // For non-blocking RecvMsg, we could return after recv once. |
| 645 | if nonblock { |
| 646 | if err != nil { |
| 647 | // Clear controlMessages when error occurs. |
| 648 | control = nil |
| 649 | } else if senderRequested && len(addr) > 0 { |
| 650 | senderAddr = socket.UnmarshalSockAddr(s.family, addr) |
| 651 | addrlen = uint32(len(addr)) |
| 652 | } |
| 653 | controlMessages := buildControlMessage(control) |
| 654 | // The socket is shutdown, report ErrWouldBlock for non-blocking mode. |
| 655 | if err == error(syscall.ESHUTDOWN) { |
| 656 | err = linuxerr.ErrWouldBlock |
| 657 | } |
| 658 | return int(n), mflag, senderAddr, addrlen, *controlMessages, syserr.FromError(err) |
| 659 | } |
| 660 | |
| 661 | // For blocking RecvMsg, we need to finish reading all data before return. |
| 662 | rn := n |
| 663 | for err == linuxerr.ErrWouldBlock || (waitall && err == nil && rn < dst.NumBytes()) { |
| 664 | dst = dst.DropFirst(int(rn)) |
| 665 | // Wait on POLLIN event. |
| 666 | if haveDeadline { |
| 667 | err = s.waitEventT(t, waiter.EventIn, deadline) |
| 668 | } else { |
| 669 | err = s.waitEvent(t, waiter.EventIn) |
| 670 | } |
| 671 | if err != nil { |
| 672 | if n == 0 { |
| 673 | // There is no POLLIN event reported before timeout. |
| 674 | if err == linuxerr.ETIMEDOUT { |
nothing calls this directly
no test coverage detected