summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2021-03-01 12:14:47 -0800
committergVisor bot <gvisor-bot@google.com>2021-03-01 12:17:20 -0800
commit865ca64ee8c0af9eba88a4a04e0730630fae6d8b (patch)
tree7afe19c2821490397e0a7fd4bad4c8e67964c6dc
parent037bb2f45abada02fb50b563f3d37381f88de7f5 (diff)
tcp: endpoint.Write has to send all data that has been read from payload
io.Reader.ReadFull returns the number of bytes copied and an error if fewer bytes were read. PiperOrigin-RevId: 360247614
-rw-r--r--pkg/tcpip/transport/tcp/endpoint.go5
-rw-r--r--test/syscalls/linux/BUILD1
-rw-r--r--test/syscalls/linux/socket_ip_tcp_generic.cc23
3 files changed, 27 insertions, 2 deletions
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go
index 83ec99fa9..f47b39ccc 100644
--- a/pkg/tcpip/transport/tcp/endpoint.go
+++ b/pkg/tcpip/transport/tcp/endpoint.go
@@ -1552,10 +1552,11 @@ func (e *endpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp
return nil, nil
}
v := make([]byte, avail)
- if _, err := io.ReadFull(p, v); err != nil {
+ n, err := p.Read(v)
+ if err != nil && err != io.EOF {
return nil, &tcpip.ErrBadBuffer{}
}
- return v, nil
+ return v[:n], nil
}()
if len(v) == 0 || err != nil {
return nil, 0, err
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index f871426f0..5371f825c 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -2384,6 +2384,7 @@ cc_library(
"@com_google_absl//absl/memory",
"@com_google_absl//absl/time",
gtest,
+ "//test/util:temp_path",
"//test/util:test_util",
"//test/util:thread_util",
],
diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc
index 579e824cd..f10f55b27 100644
--- a/test/syscalls/linux/socket_ip_tcp_generic.cc
+++ b/test/syscalls/linux/socket_ip_tcp_generic.cc
@@ -29,6 +29,7 @@
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "test/syscalls/linux/socket_test_util.h"
+#include "test/util/temp_path.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
@@ -1059,6 +1060,28 @@ TEST_P(TCPSocketPairTest, SpliceToPipe) {
SyscallSucceedsWithValue(buf.size()));
EXPECT_EQ(memcmp(rbuf.data(), buf.data(), buf.size()), 0);
}
+
+#include <sys/sendfile.h>
+
+TEST_P(TCPSocketPairTest, SendfileFromRegularFileSucceeds) {
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
+ const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
+ const FileDescriptor in_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR));
+ // Fill with some random data.
+ std::vector<char> buf(kPageSize / 2);
+ RandomizeBuffer(buf.data(), buf.size());
+ ASSERT_THAT(pwrite(in_fd.get(), buf.data(), buf.size(), 0),
+ SyscallSucceedsWithValue(buf.size()));
+
+ EXPECT_THAT(
+ sendfile(sockets->first_fd(), in_fd.get(), nullptr, buf.size() + 1),
+ SyscallSucceedsWithValue(buf.size()));
+ std::vector<char> rbuf(buf.size() + 1);
+ ASSERT_THAT(read(sockets->second_fd(), rbuf.data(), rbuf.size()),
+ SyscallSucceedsWithValue(buf.size()));
+ EXPECT_EQ(memcmp(rbuf.data(), buf.data(), buf.size()), 0);
+}
#endif // __linux__
TEST_P(TCPSocketPairTest, SetTCPWindowClampBelowMinRcvBufConnectedSocket) {