github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/socket_unix_stream.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <poll.h> 16 #include <stdio.h> 17 #include <sys/un.h> 18 19 #include "gtest/gtest.h" 20 #include "absl/time/clock.h" 21 #include "absl/time/time.h" 22 #include "test/syscalls/linux/socket_test_util.h" 23 #include "test/syscalls/linux/unix_domain_socket_test_util.h" 24 #include "test/util/test_util.h" 25 26 namespace gvisor { 27 namespace testing { 28 29 namespace { 30 31 // Test fixture for tests that apply to pairs of connected stream unix sockets. 32 using StreamUnixSocketPairTest = SocketPairTest; 33 34 TEST_P(StreamUnixSocketPairTest, WriteOneSideClosed) { 35 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 36 ASSERT_THAT(close(sockets->release_first_fd()), SyscallSucceeds()); 37 constexpr char kStr[] = "abc"; 38 ASSERT_THAT(write(sockets->second_fd(), kStr, 3), 39 SyscallFailsWithErrno(EPIPE)); 40 } 41 42 TEST_P(StreamUnixSocketPairTest, ReadOneSideClosed) { 43 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 44 ASSERT_THAT(close(sockets->release_first_fd()), SyscallSucceeds()); 45 char data[10] = {}; 46 ASSERT_THAT(read(sockets->second_fd(), data, sizeof(data)), 47 SyscallSucceedsWithValue(0)); 48 } 49 50 TEST_P(StreamUnixSocketPairTest, RecvmsgOneSideClosed) { 51 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 52 53 // Set timeout so that it will not wait for ever. 54 struct timeval tv { 55 .tv_sec = 0, .tv_usec = 10 56 }; 57 EXPECT_THAT(setsockopt(sockets->second_fd(), SOL_SOCKET, SO_RCVTIMEO, &tv, 58 sizeof(tv)), 59 SyscallSucceeds()); 60 61 ASSERT_THAT(close(sockets->release_first_fd()), SyscallSucceeds()); 62 63 char received_data[10] = {}; 64 struct iovec iov; 65 iov.iov_base = received_data; 66 iov.iov_len = sizeof(received_data); 67 struct msghdr msg = {}; 68 msg.msg_flags = -1; 69 msg.msg_iov = &iov; 70 msg.msg_iovlen = 1; 71 72 ASSERT_THAT(recvmsg(sockets->second_fd(), &msg, MSG_WAITALL), 73 SyscallSucceedsWithValue(0)); 74 } 75 76 TEST_P(StreamUnixSocketPairTest, ReadOneSideClosedWithUnreadData) { 77 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 78 79 char buf[10] = {}; 80 ASSERT_THAT(RetryEINTR(write)(sockets->second_fd(), buf, sizeof(buf)), 81 SyscallSucceedsWithValue(sizeof(buf))); 82 83 ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_RDWR), SyscallSucceeds()); 84 85 ASSERT_THAT(RetryEINTR(read)(sockets->second_fd(), buf, sizeof(buf)), 86 SyscallSucceedsWithValue(0)); 87 88 ASSERT_THAT(close(sockets->release_first_fd()), SyscallSucceeds()); 89 90 ASSERT_THAT(RetryEINTR(read)(sockets->second_fd(), buf, sizeof(buf)), 91 SyscallFailsWithErrno(ECONNRESET)); 92 } 93 94 TEST_P(StreamUnixSocketPairTest, Sendto) { 95 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 96 97 struct sockaddr_un addr = {}; 98 addr.sun_family = AF_UNIX; 99 constexpr char kPath[] = "\0nonexistent"; 100 memcpy(addr.sun_path, kPath, sizeof(kPath)); 101 102 constexpr char kStr[] = "abc"; 103 ASSERT_THAT(sendto(sockets->second_fd(), kStr, 3, 0, (struct sockaddr*)&addr, 104 sizeof(addr)), 105 SyscallFailsWithErrno(EISCONN)); 106 } 107 108 TEST_P(StreamUnixSocketPairTest, SetAndGetSocketLinger) { 109 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 110 111 struct linger sl = {1, 5}; 112 EXPECT_THAT( 113 setsockopt(sockets->first_fd(), SOL_SOCKET, SO_LINGER, &sl, sizeof(sl)), 114 SyscallSucceedsWithValue(0)); 115 116 struct linger got_linger = {}; 117 socklen_t length = sizeof(sl); 118 EXPECT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_LINGER, 119 &got_linger, &length), 120 SyscallSucceedsWithValue(0)); 121 122 ASSERT_EQ(length, sizeof(got_linger)); 123 EXPECT_EQ(0, memcmp(&got_linger, &sl, length)); 124 } 125 126 TEST_P(StreamUnixSocketPairTest, GetSocketAcceptConn) { 127 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 128 129 int got = -1; 130 socklen_t length = sizeof(got); 131 ASSERT_THAT( 132 getsockopt(sockets->first_fd(), SOL_SOCKET, SO_ACCEPTCONN, &got, &length), 133 SyscallSucceedsWithValue(0)); 134 135 ASSERT_EQ(length, sizeof(got)); 136 EXPECT_EQ(got, 0); 137 } 138 139 TEST_P(StreamUnixSocketPairTest, SetSocketSendBuf) { 140 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 141 auto s = sockets->first_fd(); 142 int max = 0; 143 int min = 0; 144 { 145 // Discover maxmimum buffer size by setting to a really large value. 146 constexpr int kRcvBufSz = INT_MAX; 147 ASSERT_THAT( 148 setsockopt(s, SOL_SOCKET, SO_SNDBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 149 SyscallSucceeds()); 150 151 max = 0; 152 socklen_t max_len = sizeof(max); 153 ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &max, &max_len), 154 SyscallSucceeds()); 155 } 156 157 { 158 // Discover minimum buffer size by setting it to zero. 159 constexpr int kRcvBufSz = 0; 160 ASSERT_THAT( 161 setsockopt(s, SOL_SOCKET, SO_SNDBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 162 SyscallSucceeds()); 163 164 socklen_t min_len = sizeof(min); 165 ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &min, &min_len), 166 SyscallSucceeds()); 167 } 168 169 int quarter_sz = min + (max - min) / 4; 170 ASSERT_THAT( 171 setsockopt(s, SOL_SOCKET, SO_SNDBUF, &quarter_sz, sizeof(quarter_sz)), 172 SyscallSucceeds()); 173 174 int val = 0; 175 socklen_t val_len = sizeof(val); 176 ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &val, &val_len), 177 SyscallSucceeds()); 178 179 // Linux doubles the value set by SO_SNDBUF/SO_SNDBUF. 180 quarter_sz *= 2; 181 ASSERT_EQ(quarter_sz, val); 182 } 183 184 TEST_P(StreamUnixSocketPairTest, IncreasedSocketSendBufUnblocksWrites) { 185 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 186 int sock = sockets->first_fd(); 187 int buf_size = 0; 188 socklen_t buf_size_len = sizeof(buf_size); 189 ASSERT_THAT(getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, &buf_size_len), 190 SyscallSucceeds()); 191 int opts; 192 ASSERT_THAT(opts = fcntl(sock, F_GETFL), SyscallSucceeds()); 193 opts |= O_NONBLOCK; 194 ASSERT_THAT(fcntl(sock, F_SETFL, opts), SyscallSucceeds()); 195 196 std::vector<char> buf(buf_size / 4); 197 // Write till the socket buffer is full. 198 while (RetryEINTR(send)(sock, buf.data(), buf.size(), 0) != -1) { 199 // Sleep to give linux a chance to move data from the send buffer to the 200 // receive buffer. 201 absl::SleepFor(absl::Milliseconds(10)); // 10ms. 202 } 203 // The last error should have been EWOULDBLOCK. 204 ASSERT_EQ(errno, EWOULDBLOCK); 205 206 // Now increase the socket send buffer. 207 buf_size = buf_size * 2; 208 ASSERT_THAT( 209 setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)), 210 SyscallSucceeds()); 211 212 // The send should succeed again. 213 ASSERT_THAT(RetryEINTR(send)(sock, buf.data(), buf.size(), 0), 214 SyscallSucceeds()); 215 } 216 217 INSTANTIATE_TEST_SUITE_P( 218 AllUnixDomainSockets, StreamUnixSocketPairTest, 219 ::testing::ValuesIn(IncludeReversals(VecCat<SocketPairKind>( 220 ApplyVec<SocketPairKind>(UnixDomainSocketPair, 221 AllBitwiseCombinations(List<int>{SOCK_STREAM}, 222 List<int>{ 223 0, SOCK_NONBLOCK})), 224 ApplyVec<SocketPairKind>(FilesystemBoundUnixDomainSocketPair, 225 AllBitwiseCombinations(List<int>{SOCK_STREAM}, 226 List<int>{ 227 0, SOCK_NONBLOCK})), 228 ApplyVec<SocketPairKind>( 229 AbstractBoundUnixDomainSocketPair, 230 AllBitwiseCombinations(List<int>{SOCK_STREAM}, 231 List<int>{0, SOCK_NONBLOCK})))))); 232 233 } // namespace 234 235 } // namespace testing 236 } // namespace gvisor