MCPcopy Index your code
hub / github.com/google/gvisor / RecvMsg

Method RecvMsg

pkg/sentry/socket/netstack/netstack.go:3297–3365  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

3295// RecvMsg implements the linux syscall recvmsg(2) for sockets backed by
3296// tcpip.Endpoint.
3297func (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

Callers

nothing calls this directly

Calls 11

recvErrMethod · 0.95
isPacketBasedMethod · 0.95
nonBlockingReadMethod · 0.95
EventRegisterMethod · 0.95
EventUnregisterMethod · 0.95
NewChannelEntryFunction · 0.92
EqualsFunction · 0.92
FromErrorFunction · 0.92
BlockWithDeadlineMethod · 0.80
NumBytesMethod · 0.45
DropFirstMethod · 0.45

Tested by

no test coverage detected