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