xref: /aosp_15_r20/external/grpc-grpc/test/core/util/fake_udp_and_tcp_server.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 // Copyright 2018 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef GRPC_TEST_CORE_UTIL_FAKE_UDP_AND_TCP_SERVER_H
18 #define GRPC_TEST_CORE_UTIL_FAKE_UDP_AND_TCP_SERVER_H
19 
20 #include <functional>
21 #include <memory>
22 #include <string>
23 #include <thread>
24 
25 #include <grpc/support/port_platform.h>
26 #include <grpc/support/sync.h>
27 
28 namespace grpc_core {
29 namespace testing {
30 
31 // This class is used to simulate a variety of network conditions in
32 // unit tests.
33 //
34 // Note that resulting server only listens on the IPv6 loopback
35 // address, "[::1]". This is expected to be OK as all known gRPC unit test
36 // environments have this address available.
37 //
38 // As examples, this can be used to (but is not limited to) exercise
39 // the following cases:
40 //
41 // 1) DNS resolver's UDP requests experience packet loss:
42 //
43 //     testing::FakeUdpAndTcpServer fake_dns_server(
44 //          testing::FakeUdpAndTcpServer::AcceptMode::
45 //             kWaitForClientToSendFirstBytes,
46 //     testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
47 //     auto server_uri = absl::StrFormat("dns:///[::]:%d/localhost:1234",
48 //         fake_dns_server.port());
49 //
50 // 2) Server gets stuck while setting up a security handshake and client's
51 //    security handshake times out (requires using secure channels):
52 //
53 //     testing::FakeUdpAndTcpServer fake_server(
54 //          testing::FakeUdpAndTcpServer::AcceptMode::
55 //             kWaitForClientToSendFirstBytes,
56 //     testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
57 //     auto server_uri = absl::StrFormat("[::1]:%d", fake_server.port());
58 //
59 // 3) Client connections are immediately closed after sending the first bytes
60 //    to an insecure server:
61 //
62 //     testing::FakeUdpAndTcpServer fake_server(
63 //          testing::FakeUdpAndTcpServer::AcceptMode::
64 //             kEagerlySendSettings,
65 //     testing::FakeUdpAndTcpServer::CloseSocketUponReceivingBytesFromPeer);
66 //     auto server_uri = absl::StrFormat("[::1]:%d", fake_server.port());
67 //
68 class FakeUdpAndTcpServer {
69  public:
70   enum class ProcessReadResult {
71     kContinueReading = 0,
72     kCloseSocket,
73   };
74 
75   enum class AcceptMode {
76     kWaitForClientToSendFirstBytes,  // useful for emulating ALTS based
77                                      // grpc servers
78     kEagerlySendSettings,  // useful for emulating insecure grpc servers (e.g.
79                            // ALTS handshake servers)
80   };
81 
82   explicit FakeUdpAndTcpServer(
83       AcceptMode accept_mode,
84       std::function<ProcessReadResult(int, int, int)> process_read_cb);
85 
86   ~FakeUdpAndTcpServer();
87 
address()88   const char* address() { return address_.c_str(); }
89 
port()90   int port() { return port_; };
91 
92   static ProcessReadResult CloseSocketUponReceivingBytesFromPeer(
93       int bytes_received_size, int read_error, int s);
94 
95   static ProcessReadResult CloseSocketUponCloseFromPeer(int bytes_received_size,
96                                                         int read_error, int s);
97 
98   static ProcessReadResult SendThreeAllZeroBytes(int bytes_received_size,
99                                                  int read_error, int s);
100 
101   void ReadFromUdpSocket();
102 
103   // Run a loop that periodically, every 10 ms:
104   //   1) Checks if there are any new TCP connections to accept.
105   //   2) Checks if any data has arrived yet on established connections,
106   //      and reads from them if so, processing the sockets as configured.
107   void RunServerLoop();
108 
109  private:
110   class FakeUdpAndTcpServerPeer {
111    public:
112     explicit FakeUdpAndTcpServerPeer(int fd);
113 
114     ~FakeUdpAndTcpServerPeer();
115 
116     void MaybeContinueSendingSettings();
117 
fd()118     int fd() { return fd_; }
119 
120    private:
121     int fd_;
122     int total_bytes_sent_ = 0;
123   };
124 
125   int accept_socket_;
126   int udp_socket_;
127   int port_;
128   gpr_event stop_ev_;
129   std::string address_;
130   std::unique_ptr<std::thread> run_server_loop_thd_;
131   const AcceptMode accept_mode_;
132   std::function<ProcessReadResult(int, int, int)> process_read_cb_;
133 };
134 
135 }  // namespace testing
136 }  // namespace grpc_core
137 
138 #endif  // GRPC_TEST_CORE_UTIL_FAKE_UDP_AND_TCP_SERVER_H
139