tcp_client_posix_test.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "src/core/lib/gprpp/time.h"
  19. #include "src/core/lib/iomgr/port.h"
  20. // This test won't work except with posix sockets enabled
  21. #ifdef GRPC_POSIX_SOCKET_TCP_CLIENT
  22. #include <errno.h>
  23. #include <netinet/in.h>
  24. #include <string.h>
  25. #include <sys/socket.h>
  26. #include <unistd.h>
  27. #include <grpc/grpc.h>
  28. #include <grpc/support/alloc.h>
  29. #include <grpc/support/log.h>
  30. #include <grpc/support/time.h>
  31. #include "src/core/lib/iomgr/iomgr.h"
  32. #include "src/core/lib/iomgr/pollset_set.h"
  33. #include "src/core/lib/iomgr/socket_utils_posix.h"
  34. #include "src/core/lib/iomgr/tcp_client.h"
  35. #include "src/core/lib/iomgr/timer.h"
  36. #include "src/core/lib/resource_quota/api.h"
  37. #include "test/core/util/test_config.h"
  38. static grpc_pollset_set* g_pollset_set;
  39. static gpr_mu* g_mu;
  40. static grpc_pollset* g_pollset;
  41. static int g_connections_complete = 0;
  42. static grpc_endpoint* g_connecting = nullptr;
  43. static grpc_core::Timestamp test_deadline(void) {
  44. return grpc_core::Timestamp::FromTimespecRoundUp(
  45. grpc_timeout_seconds_to_deadline(10));
  46. }
  47. static void finish_connection() {
  48. gpr_mu_lock(g_mu);
  49. g_connections_complete++;
  50. grpc_core::ExecCtx exec_ctx;
  51. GPR_ASSERT(
  52. GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, nullptr)));
  53. gpr_mu_unlock(g_mu);
  54. }
  55. static void must_succeed(void* /*arg*/, grpc_error_handle error) {
  56. GPR_ASSERT(g_connecting != nullptr);
  57. GPR_ASSERT(error == GRPC_ERROR_NONE);
  58. grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  59. "must_succeed called"));
  60. grpc_endpoint_destroy(g_connecting);
  61. g_connecting = nullptr;
  62. finish_connection();
  63. }
  64. static void must_fail(void* /*arg*/, grpc_error_handle error) {
  65. GPR_ASSERT(g_connecting == nullptr);
  66. GPR_ASSERT(error != GRPC_ERROR_NONE);
  67. finish_connection();
  68. }
  69. void test_succeeds(void) {
  70. gpr_log(GPR_ERROR, "---- starting test_succeeds() ----");
  71. grpc_resolved_address resolved_addr;
  72. struct sockaddr_in* addr =
  73. reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
  74. int svr_fd;
  75. int r;
  76. int connections_complete_before;
  77. grpc_closure done;
  78. grpc_core::ExecCtx exec_ctx;
  79. memset(&resolved_addr, 0, sizeof(resolved_addr));
  80. resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
  81. addr->sin_family = AF_INET;
  82. /* create a phony server */
  83. svr_fd = socket(AF_INET, SOCK_STREAM, 0);
  84. GPR_ASSERT(svr_fd >= 0);
  85. GPR_ASSERT(
  86. 0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
  87. GPR_ASSERT(0 == listen(svr_fd, 1));
  88. gpr_mu_lock(g_mu);
  89. connections_complete_before = g_connections_complete;
  90. gpr_mu_unlock(g_mu);
  91. /* connect to it */
  92. GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr,
  93. (socklen_t*)&resolved_addr.len) == 0);
  94. GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
  95. const grpc_channel_args* args = grpc_core::CoreConfiguration::Get()
  96. .channel_args_preconditioning()
  97. .PreconditionChannelArgs(nullptr);
  98. grpc_tcp_client_connect(&done, &g_connecting, g_pollset_set, args,
  99. &resolved_addr, grpc_core::Timestamp::InfFuture());
  100. grpc_channel_args_destroy(args);
  101. /* await the connection */
  102. do {
  103. resolved_addr.len = static_cast<socklen_t>(sizeof(addr));
  104. r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
  105. reinterpret_cast<socklen_t*>(&resolved_addr.len));
  106. } while (r == -1 && errno == EINTR);
  107. GPR_ASSERT(r >= 0);
  108. close(r);
  109. gpr_mu_lock(g_mu);
  110. while (g_connections_complete == connections_complete_before) {
  111. grpc_pollset_worker* worker = nullptr;
  112. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  113. "pollset_work",
  114. grpc_pollset_work(g_pollset, &worker,
  115. grpc_core::Timestamp::FromTimespecRoundUp(
  116. grpc_timeout_seconds_to_deadline(5)))));
  117. gpr_mu_unlock(g_mu);
  118. grpc_core::ExecCtx::Get()->Flush();
  119. gpr_mu_lock(g_mu);
  120. }
  121. gpr_mu_unlock(g_mu);
  122. gpr_log(GPR_ERROR, "---- finished test_succeeds() ----");
  123. }
  124. void test_fails(void) {
  125. gpr_log(GPR_ERROR, "---- starting test_fails() ----");
  126. grpc_resolved_address resolved_addr;
  127. struct sockaddr_in* addr =
  128. reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
  129. int connections_complete_before;
  130. grpc_closure done;
  131. grpc_core::ExecCtx exec_ctx;
  132. memset(&resolved_addr, 0, sizeof(resolved_addr));
  133. resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
  134. addr->sin_family = AF_INET;
  135. gpr_mu_lock(g_mu);
  136. connections_complete_before = g_connections_complete;
  137. gpr_mu_unlock(g_mu);
  138. /* connect to a broken address */
  139. GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
  140. grpc_tcp_client_connect(&done, &g_connecting, g_pollset_set, nullptr,
  141. &resolved_addr, grpc_core::Timestamp::InfFuture());
  142. gpr_mu_lock(g_mu);
  143. /* wait for the connection callback to finish */
  144. while (g_connections_complete == connections_complete_before) {
  145. grpc_pollset_worker* worker = nullptr;
  146. grpc_core::Timestamp polling_deadline = test_deadline();
  147. switch (grpc_timer_check(&polling_deadline)) {
  148. case GRPC_TIMERS_FIRED:
  149. break;
  150. case GRPC_TIMERS_NOT_CHECKED:
  151. polling_deadline = grpc_core::Timestamp::ProcessEpoch();
  152. ABSL_FALLTHROUGH_INTENDED;
  153. case GRPC_TIMERS_CHECKED_AND_EMPTY:
  154. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  155. "pollset_work",
  156. grpc_pollset_work(g_pollset, &worker, polling_deadline)));
  157. break;
  158. }
  159. gpr_mu_unlock(g_mu);
  160. grpc_core::ExecCtx::Get()->Flush();
  161. gpr_mu_lock(g_mu);
  162. }
  163. gpr_mu_unlock(g_mu);
  164. gpr_log(GPR_ERROR, "---- finished test_fails() ----");
  165. }
  166. void test_fails_bad_addr_no_leak(void) {
  167. gpr_log(GPR_ERROR, "---- starting test_fails_bad_addr_no_leak() ----");
  168. grpc_resolved_address resolved_addr;
  169. struct sockaddr_in* addr =
  170. reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
  171. int connections_complete_before;
  172. grpc_closure done;
  173. grpc_core::ExecCtx exec_ctx;
  174. memset(&resolved_addr, 0, sizeof(resolved_addr));
  175. resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
  176. // force `grpc_tcp_client_prepare_fd` to fail. contrived, but effective.
  177. addr->sin_family = AF_IPX;
  178. gpr_mu_lock(g_mu);
  179. connections_complete_before = g_connections_complete;
  180. gpr_mu_unlock(g_mu);
  181. // connect to an invalid address.
  182. GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
  183. grpc_tcp_client_connect(&done, &g_connecting, g_pollset_set, nullptr,
  184. &resolved_addr, grpc_core::Timestamp::InfFuture());
  185. gpr_mu_lock(g_mu);
  186. while (g_connections_complete == connections_complete_before) {
  187. grpc_pollset_worker* worker = nullptr;
  188. grpc_core::Timestamp polling_deadline = test_deadline();
  189. switch (grpc_timer_check(&polling_deadline)) {
  190. case GRPC_TIMERS_FIRED:
  191. break;
  192. case GRPC_TIMERS_NOT_CHECKED:
  193. polling_deadline = grpc_core::Timestamp::ProcessEpoch();
  194. ABSL_FALLTHROUGH_INTENDED;
  195. case GRPC_TIMERS_CHECKED_AND_EMPTY:
  196. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  197. "pollset_work",
  198. grpc_pollset_work(g_pollset, &worker, polling_deadline)));
  199. break;
  200. }
  201. gpr_mu_unlock(g_mu);
  202. grpc_core::ExecCtx::Get()->Flush();
  203. gpr_mu_lock(g_mu);
  204. }
  205. gpr_mu_unlock(g_mu);
  206. gpr_log(GPR_ERROR, "---- finished test_fails_bad_addr_no_leak() ----");
  207. }
  208. static void destroy_pollset(void* p, grpc_error_handle /*error*/) {
  209. grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
  210. }
  211. int main(int argc, char** argv) {
  212. grpc_closure destroyed;
  213. grpc::testing::TestEnvironment env(argc, argv);
  214. grpc_init();
  215. {
  216. grpc_core::ExecCtx exec_ctx;
  217. g_pollset_set = grpc_pollset_set_create();
  218. g_pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  219. grpc_pollset_init(g_pollset, &g_mu);
  220. grpc_pollset_set_add_pollset(g_pollset_set, g_pollset);
  221. test_succeeds();
  222. test_fails();
  223. test_fails_bad_addr_no_leak();
  224. grpc_pollset_set_destroy(g_pollset_set);
  225. GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset,
  226. grpc_schedule_on_exec_ctx);
  227. grpc_pollset_shutdown(g_pollset, &destroyed);
  228. }
  229. grpc_shutdown();
  230. gpr_free(g_pollset);
  231. return 0;
  232. }
  233. #else /* GRPC_POSIX_SOCKET_TCP_CLIENT */
  234. int main(int argc, char** argv) { return 1; }
  235. #endif /* GRPC_POSIX_SOCKET_CLIENT */