recv is a helper function for doing non-blocking read once. It returns: 1. number of bytes received; 2. sender address for non-stream socket; 3. control message; 4. message flag; 5. internal error if any
(t *kernel.Task, dst usermem.IOSequence, sysflags int, addr []byte, control []byte)
| 574 | // 4. message flag; |
| 575 | // 5. internal error if any |
| 576 | func (s *socketOperations) recv(t *kernel.Task, dst usermem.IOSequence, sysflags int, addr []byte, control []byte) (int64, []byte, []byte, int, error) { |
| 577 | bytes := dst.NumBytes() |
| 578 | // Directly return if dst is empty. |
| 579 | if bytes == 0 { |
| 580 | return 0, addr, control, 0, nil |
| 581 | } |
| 582 | |
| 583 | // Slow path for non-stream socket(e.g., UDP, raw socket). |
| 584 | if s.skType != linux.SOCK_STREAM { |
| 585 | if len(addr) == 0 && s.skType == linux.SOCK_DGRAM { |
| 586 | addr = make([]byte, sizeofSockaddr) |
| 587 | } |
| 588 | |
| 589 | tmpBuf := make([]byte, bytes) |
| 590 | tmpBS := safemem.BlockSeqOf(safemem.BlockFromSafeSlice(tmpBuf)) |
| 591 | iovs := iovecsFromBlockSeq(tmpBS, nil) |
| 592 | rc, la, lc, flag := cgo.Recvmsg(s.fd, iovs, addr, control, sysflags) |
| 593 | if rc < 0 { |
| 594 | _, err := translateReturn(rc) |
| 595 | return 0, addr /* return the original slice */, control /* return the original slice */, 0, err |
| 596 | } |
| 597 | |
| 598 | n, err := dst.CopyOut(t, tmpBuf[:rc]) |
| 599 | return int64(n), addr[:la], control[:lc], flag, err |
| 600 | } |
| 601 | |
| 602 | // Fast path for stream socket(e.g., TCP socket). |
| 603 | rw := getReadWriter(s.fd) |
| 604 | rw.to = control |
| 605 | rw.flags = uint32(sysflags) |
| 606 | |
| 607 | n, err := dst.CopyOutFrom(t, rw) |
| 608 | |
| 609 | control = rw.to |
| 610 | msgFlags := int(rw.flags) |
| 611 | putReadWriter(rw) |
| 612 | |
| 613 | return n, nil /* ignore for TCP */, control, msgFlags, err |
| 614 | } |
| 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) { |
no test coverage detected