MCPcopy
hub / github.com/google/gvisor / SendMsg

Method SendMsg

pkg/sentry/socket/netstack/netstack.go:3369–3439  ·  view source on GitHub ↗

SendMsg implements the linux syscall sendmsg(2) for sockets backed by tcpip.Endpoint.

(t *kernel.Task, src usermem.IOSequence, to []byte, flags int, haveDeadline bool, deadline ktime.Time, controlMessages socket.ControlMessages)

Source from the content-addressed store, hash-verified

3367// SendMsg implements the linux syscall sendmsg(2) for sockets backed by
3368// tcpip.Endpoint.
3369func (s *sock) SendMsg(t *kernel.Task, src usermem.IOSequence, to []byte, flags int, haveDeadline bool, deadline ktime.Time, controlMessages socket.ControlMessages) (int, *syserr.Error) {
3370 // Reject Unix control messages.
3371 if !controlMessages.Unix.Empty() {
3372 return 0, syserr.ErrInvalidArgument
3373 }
3374
3375 var addr *tcpip.FullAddress
3376 if len(to) > 0 {
3377 addrBuf, family, err := socket.AddressAndFamily(to)
3378 if err != nil {
3379 return 0, err
3380 }
3381 if !s.checkFamily(family, false /* exact */) {
3382 return 0, syserr.ErrInvalidArgument
3383 }
3384 addrBuf = s.mapFamily(addrBuf, family)
3385
3386 addr = &addrBuf
3387 }
3388
3389 opts := tcpip.WriteOptions{
3390 To: addr,
3391 More: flags&linux.MSG_MORE != 0,
3392 EndOfRecord: flags&linux.MSG_EOR != 0,
3393 ControlMessages: s.linuxToNetstackControlMessages(controlMessages),
3394 }
3395
3396 r := src.Reader(t)
3397 var (
3398 total int64
3399 entry waiter.Entry
3400 ch <-chan struct{}
3401 )
3402 for {
3403 n, err := s.Endpoint.Write(r, opts)
3404 total += n
3405 if flags&linux.MSG_DONTWAIT != 0 {
3406 return int(total), syserr.TranslateNetstackError(err)
3407 }
3408 block := true
3409 switch err.(type) {
3410 case nil:
3411 block = total != src.NumBytes()
3412 case *tcpip.ErrWouldBlock:
3413 default:
3414 block = false
3415 }
3416 if block {
3417 if ch == nil {
3418 // We'll have to block. Register for notification and keep trying to
3419 // send all the data.
3420 entry, ch = waiter.NewChannelEntry(waiter.WritableEvents)
3421 s.EventRegister(&entry)
3422 defer s.EventUnregister(&entry)
3423 } else {
3424 // Don't wait immediately after registration in case more data
3425 // became available between when we last checked and when we setup
3426 // the notification.

Callers

nothing calls this directly

Calls 15

checkFamilyMethod · 0.95
mapFamilyMethod · 0.95
EventRegisterMethod · 0.95
EventUnregisterMethod · 0.95
AddressAndFamilyFunction · 0.92
TranslateNetstackErrorFunction · 0.92
NewChannelEntryFunction · 0.92
EqualsFunction · 0.92
FromErrorFunction · 0.92
BlockWithDeadlineMethod · 0.80
WriteMethod · 0.65

Tested by

no test coverage detected