RecvMsg implements the linux syscall recvmsg(2) for sockets backed by a transport.Endpoint.
(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64)
| 756 | // RecvMsg implements the linux syscall recvmsg(2) for sockets backed by |
| 757 | // a transport.Endpoint. |
| 758 | func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64) (n int, msgFlags int, senderAddr linux.SockAddr, senderAddrLen uint32, controlMessages socket.ControlMessages, err *syserr.Error) { |
| 759 | trunc := flags&linux.MSG_TRUNC != 0 |
| 760 | peek := flags&linux.MSG_PEEK != 0 |
| 761 | dontWait := flags&linux.MSG_DONTWAIT != 0 |
| 762 | waitAll := flags&linux.MSG_WAITALL != 0 |
| 763 | isPacket := s.isPacket() |
| 764 | |
| 765 | // Calculate the number of FDs for which we have space and if we are |
| 766 | // requesting credentials. |
| 767 | var wantCreds bool |
| 768 | rightsLen := int(controlDataLen) - unix.SizeofCmsghdr |
| 769 | if s.Passcred() { |
| 770 | // Credentials take priority if they are enabled and there is space. |
| 771 | wantCreds = rightsLen > 0 |
| 772 | if !wantCreds { |
| 773 | msgFlags |= linux.MSG_CTRUNC |
| 774 | } |
| 775 | credLen := unix.CmsgSpace(unix.SizeofUcred) |
| 776 | rightsLen -= credLen |
| 777 | } |
| 778 | // FDs are 32 bit (4 byte) ints. |
| 779 | numRights := rightsLen / 4 |
| 780 | if numRights < 0 { |
| 781 | numRights = 0 |
| 782 | } |
| 783 | |
| 784 | r := EndpointReader{ |
| 785 | Ctx: t, |
| 786 | Endpoint: s.ep, |
| 787 | Creds: wantCreds, |
| 788 | NumRights: numRights, |
| 789 | Peek: peek, |
| 790 | } |
| 791 | |
| 792 | doRead := func() (int64, error) { |
| 793 | n, err := dst.CopyOutFrom(t, &r) |
| 794 | if r.Notify != nil { |
| 795 | r.Notify() |
| 796 | } |
| 797 | return n, err |
| 798 | } |
| 799 | |
| 800 | // Drop any unused rights messages after reading. |
| 801 | defer func() { |
| 802 | for _, rm := range r.UnusedRights { |
| 803 | rm.Release(t) |
| 804 | } |
| 805 | }() |
| 806 | |
| 807 | // If MSG_TRUNC is set with a zero byte destination then we still need |
| 808 | // to read the message and discard it, or in the case where MSG_PEEK is |
| 809 | // set, leave it be. In both cases the full message length must be |
| 810 | // returned. |
| 811 | if trunc && dst.Addrs.NumBytes() == 0 { |
| 812 | doRead = func() (int64, error) { |
| 813 | err := r.Truncate() |
| 814 | // Always return zero for bytes read since the destination size is |
| 815 | // zero. |
nothing calls this directly
no test coverage detected