mirror of
https://github.com/hanzoai/visor.git
synced 2026-09-24 17:04:14 +00:00
This is needed so that connectioned endpoint in the transport package can use this endpoint to implement host FD based binded endpoints. I had to simplify some other dependencies to make this possible. - Removed uniqueid's dependency on transport package completely. - Removed SCMConnectedEndpoint and HostConnectedEndpoint's dependency on control package so they could be moved to transport. control already depends on transport. - scmRights struct from fsimpl/host/control.go had to be moved into transport so that HostConnectedEndpoint could be implemented. But scmRights.Fill() could not be moved because it inherently depends on making vfs.FileDescriptions which depends on vfs which in turn depends on transport. So now that scmRights -> vfs.FD conversion happens in the syscall package. PiperOrigin-RevId: 413839350
110 lines
2.6 KiB
Go
110 lines
2.6 KiB
Go
// Copyright 2020 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package transport
|
|
|
|
import (
|
|
"golang.org/x/sys/unix"
|
|
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
|
"gvisor.dev/gvisor/pkg/sentry/hostfd"
|
|
)
|
|
|
|
// copyToMulti copies as many bytes from src to dst as possible.
|
|
func copyToMulti(dst [][]byte, src []byte) {
|
|
for _, d := range dst {
|
|
done := copy(d, src)
|
|
src = src[done:]
|
|
if len(src) == 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// copyFromMulti copies as many bytes from src to dst as possible.
|
|
func copyFromMulti(dst []byte, src [][]byte) {
|
|
for _, s := range src {
|
|
done := copy(dst, s)
|
|
dst = dst[done:]
|
|
if len(dst) == 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// buildIovec builds an iovec slice from the given []byte slice.
|
|
//
|
|
// If truncate, truncate bufs > maxlen. Otherwise, immediately return an error.
|
|
//
|
|
// If length < the total length of bufs, err indicates why, even when returning
|
|
// a truncated iovec.
|
|
//
|
|
// If intermediate != nil, iovecs references intermediate rather than bufs and
|
|
// the caller must copy to/from bufs as necessary.
|
|
func buildIovec(bufs [][]byte, maxlen int64, truncate bool) (length int64, iovecs []unix.Iovec, intermediate []byte, err error) {
|
|
var iovsRequired int
|
|
for _, b := range bufs {
|
|
length += int64(len(b))
|
|
if len(b) > 0 {
|
|
iovsRequired++
|
|
}
|
|
}
|
|
|
|
stopLen := length
|
|
if length > maxlen {
|
|
if truncate {
|
|
stopLen = maxlen
|
|
err = linuxerr.EAGAIN
|
|
} else {
|
|
return 0, nil, nil, linuxerr.EMSGSIZE
|
|
}
|
|
}
|
|
|
|
if iovsRequired > hostfd.MaxSendRecvMsgIov {
|
|
// The kernel will reject our call if we pass this many iovs.
|
|
// Use a single intermediate buffer instead.
|
|
b := make([]byte, stopLen)
|
|
|
|
return stopLen, []unix.Iovec{{
|
|
Base: &b[0],
|
|
Len: uint64(stopLen),
|
|
}}, b, err
|
|
}
|
|
|
|
var total int64
|
|
iovecs = make([]unix.Iovec, 0, iovsRequired)
|
|
for i := range bufs {
|
|
l := len(bufs[i])
|
|
if l == 0 {
|
|
continue
|
|
}
|
|
|
|
stop := int64(l)
|
|
if total+stop > stopLen {
|
|
stop = stopLen - total
|
|
}
|
|
|
|
iovecs = append(iovecs, unix.Iovec{
|
|
Base: &bufs[i][0],
|
|
Len: uint64(stop),
|
|
})
|
|
|
|
total += stop
|
|
if total >= stopLen {
|
|
break
|
|
}
|
|
}
|
|
|
|
return total, iovecs, nil, err
|
|
}
|