• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The gRPC 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 <sys/socket.h>
16 #include <unistd.h>
17 
18 #include <memory>
19 
20 #include "absl/status/status.h"
21 #include "gtest/gtest.h"
22 
23 #include <grpc/grpc.h>
24 
25 #include "src/core/lib/iomgr/port.h"
26 
27 // IWYU pragma: no_include <arpa/inet.h>
28 
29 // This test won't work except with posix sockets enabled
30 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
31 
32 #include <netinet/in.h>
33 #include <netinet/ip.h>
34 
35 #include <grpc/support/alloc.h>
36 
37 #include "src/core/lib/event_engine/posix_engine/tcp_socket_utils.h"
38 #include "src/core/lib/gpr/useful.h"
39 #include "src/core/lib/iomgr/socket_mutator.h"
40 
41 namespace grpc_event_engine {
42 namespace experimental {
43 
44 namespace {
45 
46 struct test_socket_mutator {
47   grpc_socket_mutator base;
48   int option_value;
49 };
50 
MutateFd(int fd,grpc_socket_mutator * mutator)51 bool MutateFd(int fd, grpc_socket_mutator* mutator) {
52   int newval;
53   socklen_t intlen = sizeof(newval);
54   struct test_socket_mutator* m =
55       reinterpret_cast<struct test_socket_mutator*>(mutator);
56 
57   if (0 != setsockopt(fd, IPPROTO_IP, IP_TOS, &m->option_value,
58                       sizeof(m->option_value))) {
59     return false;
60   }
61   if (0 != getsockopt(fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
62     return false;
63   }
64   if (newval != m->option_value) {
65     return false;
66   }
67   return true;
68 }
69 
MutateFd2(const grpc_mutate_socket_info * info,grpc_socket_mutator * mutator)70 bool MutateFd2(const grpc_mutate_socket_info* info,
71                grpc_socket_mutator* mutator) {
72   int newval;
73   socklen_t intlen = sizeof(newval);
74   struct test_socket_mutator* m =
75       reinterpret_cast<struct test_socket_mutator*>(mutator);
76 
77   if (0 != setsockopt(info->fd, IPPROTO_IP, IP_TOS, &m->option_value,
78                       sizeof(m->option_value))) {
79     return false;
80   }
81   if (0 != getsockopt(info->fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
82     return false;
83   }
84   if (newval != m->option_value) {
85     return false;
86   }
87   return true;
88 }
89 
DestroyTestMutator(grpc_socket_mutator * mutator)90 void DestroyTestMutator(grpc_socket_mutator* mutator) {
91   struct test_socket_mutator* m =
92       reinterpret_cast<struct test_socket_mutator*>(mutator);
93   gpr_free(m);
94 }
95 
CompareTestMutator(grpc_socket_mutator * a,grpc_socket_mutator * b)96 int CompareTestMutator(grpc_socket_mutator* a, grpc_socket_mutator* b) {
97   struct test_socket_mutator* ma =
98       reinterpret_cast<struct test_socket_mutator*>(a);
99   struct test_socket_mutator* mb =
100       reinterpret_cast<struct test_socket_mutator*>(b);
101   return grpc_core::QsortCompare(ma->option_value, mb->option_value);
102 }
103 
104 const grpc_socket_mutator_vtable mutator_vtable = {MutateFd, CompareTestMutator,
105                                                    DestroyTestMutator, nullptr};
106 
107 const grpc_socket_mutator_vtable mutator_vtable2 = {
108     nullptr, CompareTestMutator, DestroyTestMutator, MutateFd2};
109 
110 }  // namespace
111 
TEST(TcpPosixSocketUtilsTest,SocketMutatorTest)112 TEST(TcpPosixSocketUtilsTest, SocketMutatorTest) {
113   auto test_with_vtable = [](const grpc_socket_mutator_vtable* vtable) {
114     int sock = socket(PF_INET, SOCK_STREAM, 0);
115     if (sock < 0) {
116       // Try ipv6
117       sock = socket(AF_INET6, SOCK_STREAM, 0);
118     }
119     EXPECT_GT(sock, 0);
120     PosixSocketWrapper posix_sock(sock);
121     struct test_socket_mutator mutator;
122     grpc_socket_mutator_init(&mutator.base, vtable);
123 
124     mutator.option_value = IPTOS_LOWDELAY;
125     EXPECT_TRUE(
126         posix_sock
127             .SetSocketMutator(GRPC_FD_CLIENT_CONNECTION_USAGE,
128                               reinterpret_cast<grpc_socket_mutator*>(&mutator))
129             .ok());
130     mutator.option_value = IPTOS_THROUGHPUT;
131     EXPECT_TRUE(
132         posix_sock
133             .SetSocketMutator(GRPC_FD_CLIENT_CONNECTION_USAGE,
134                               reinterpret_cast<grpc_socket_mutator*>(&mutator))
135             .ok());
136 
137     mutator.option_value = IPTOS_RELIABILITY;
138     EXPECT_TRUE(
139         posix_sock
140             .SetSocketMutator(GRPC_FD_CLIENT_CONNECTION_USAGE,
141                               reinterpret_cast<grpc_socket_mutator*>(&mutator))
142             .ok());
143 
144     mutator.option_value = -1;
145     EXPECT_FALSE(
146         posix_sock
147             .SetSocketMutator(GRPC_FD_CLIENT_CONNECTION_USAGE,
148                               reinterpret_cast<grpc_socket_mutator*>(&mutator))
149             .ok());
150     close(sock);
151   };
152   test_with_vtable(&mutator_vtable);
153   test_with_vtable(&mutator_vtable2);
154 }
155 
TEST(TcpPosixSocketUtilsTest,SocketOptionsTest)156 TEST(TcpPosixSocketUtilsTest, SocketOptionsTest) {
157   int sock = socket(PF_INET, SOCK_STREAM, 0);
158   if (sock < 0) {
159     // Try ipv6
160     sock = socket(AF_INET6, SOCK_STREAM, 0);
161   }
162   EXPECT_GT(sock, 0);
163   PosixSocketWrapper posix_sock(sock);
164   EXPECT_TRUE(posix_sock.SetSocketNonBlocking(1).ok());
165   EXPECT_TRUE(posix_sock.SetSocketNonBlocking(0).ok());
166   EXPECT_TRUE(posix_sock.SetSocketCloexec(1).ok());
167   EXPECT_TRUE(posix_sock.SetSocketCloexec(0).ok());
168   EXPECT_TRUE(posix_sock.SetSocketReuseAddr(1).ok());
169   EXPECT_TRUE(posix_sock.SetSocketReuseAddr(0).ok());
170   EXPECT_TRUE(posix_sock.SetSocketLowLatency(1).ok());
171   EXPECT_TRUE(posix_sock.SetSocketLowLatency(0).ok());
172   close(sock);
173 }
174 
175 }  // namespace experimental
176 }  // namespace grpc_event_engine
177 
main(int argc,char ** argv)178 int main(int argc, char** argv) {
179   ::testing::InitGoogleTest(&argc, argv);
180   return RUN_ALL_TESTS();
181 }
182 
183 #else  // GRPC_POSIX_SOCKET_UTILS_COMMON
184 
main(int argc,char ** argv)185 int main(int argc, char** argv) { return 0; }
186 
187 #endif  // GRPC_POSIX_SOCKET_UTILS_COMMON
188