RecvMsg implements the linux syscall recvmsg(2) for sockets backed by tcpip.Endpoint.
(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, _ uint64)
| 3295 | // RecvMsg implements the linux syscall recvmsg(2) for sockets backed by |
| 3296 | // tcpip.Endpoint. |
| 3297 | func (s *sock) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, _ uint64) (n int, msgFlags int, senderAddr linux.SockAddr, senderAddrLen uint32, controlMessages socket.ControlMessages, err *syserr.Error) { |
| 3298 | if flags&linux.MSG_ERRQUEUE != 0 { |
| 3299 | return s.recvErr(t, dst) |
| 3300 | } |
| 3301 | |
| 3302 | trunc := flags&linux.MSG_TRUNC != 0 |
| 3303 | peek := flags&linux.MSG_PEEK != 0 |
| 3304 | dontWait := flags&linux.MSG_DONTWAIT != 0 |
| 3305 | waitAll := flags&linux.MSG_WAITALL != 0 |
| 3306 | if senderRequested && !s.isPacketBased() { |
| 3307 | // Stream sockets ignore the sender address. |
| 3308 | senderRequested = false |
| 3309 | } |
| 3310 | n, msgFlags, senderAddr, senderAddrLen, controlMessages, err = s.nonBlockingRead(t, dst, peek, trunc, senderRequested) |
| 3311 | |
| 3312 | if s.isPacketBased() && err == syserr.ErrClosedForReceive && flags&linux.MSG_DONTWAIT != 0 { |
| 3313 | // In this situation we should return EAGAIN. |
| 3314 | return 0, 0, nil, 0, socket.ControlMessages{}, syserr.ErrTryAgain |
| 3315 | } |
| 3316 | |
| 3317 | if err != nil && (err != syserr.ErrWouldBlock || dontWait) { |
| 3318 | // Read failed and we should not retry. |
| 3319 | return 0, 0, nil, 0, socket.ControlMessages{}, err |
| 3320 | } |
| 3321 | |
| 3322 | if err == nil && (dontWait || !waitAll || s.isPacketBased() || int64(n) >= dst.NumBytes()) { |
| 3323 | // We got all the data we need. |
| 3324 | return |
| 3325 | } |
| 3326 | |
| 3327 | // Don't overwrite any data we received. |
| 3328 | dst = dst.DropFirst(n) |
| 3329 | |
| 3330 | // We'll have to block. Register for notifications and keep trying to |
| 3331 | // send all the data. |
| 3332 | e, ch := waiter.NewChannelEntry(waiter.ReadableEvents) |
| 3333 | s.EventRegister(&e) |
| 3334 | defer s.EventUnregister(&e) |
| 3335 | |
| 3336 | for { |
| 3337 | var rn int |
| 3338 | rn, msgFlags, senderAddr, senderAddrLen, controlMessages, err = s.nonBlockingRead(t, dst, peek, trunc, senderRequested) |
| 3339 | n += rn |
| 3340 | if err != nil && err != syserr.ErrWouldBlock { |
| 3341 | // Always stop on errors other than would block as we generally |
| 3342 | // won't be able to get any more data. Eat the error if we got |
| 3343 | // any data. |
| 3344 | if n > 0 { |
| 3345 | err = nil |
| 3346 | } |
| 3347 | return |
| 3348 | } |
| 3349 | if err == nil && (s.isPacketBased() || !waitAll || int64(rn) >= dst.NumBytes()) { |
| 3350 | // We got all the data we need. |
| 3351 | return |
| 3352 | } |
| 3353 | dst = dst.DropFirst(rn) |
| 3354 |
nothing calls this directly
no test coverage detected