port_server_client.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 <grpc/support/port_platform.h>
  19. #include "test/core/util/test_config.h"
  20. #ifdef GRPC_TEST_PICK_PORT
  21. #include <math.h>
  22. #include <string.h>
  23. #include "absl/strings/str_format.h"
  24. #include <grpc/grpc.h>
  25. #include <grpc/support/alloc.h>
  26. #include <grpc/support/log.h>
  27. #include <grpc/support/string_util.h>
  28. #include <grpc/support/sync.h>
  29. #include <grpc/support/time.h>
  30. #include "src/core/lib/http/httpcli.h"
  31. #include "test/core/util/port_server_client.h"
  32. typedef struct freereq {
  33. gpr_mu* mu = nullptr;
  34. grpc_polling_entity pops = {};
  35. int done = 0;
  36. } freereq;
  37. static void destroy_pops_and_shutdown(void* p, grpc_error_handle /*error*/) {
  38. grpc_pollset* pollset =
  39. grpc_polling_entity_pollset(static_cast<grpc_polling_entity*>(p));
  40. grpc_pollset_destroy(pollset);
  41. gpr_free(pollset);
  42. }
  43. static void freed_port_from_server(void* arg, grpc_error_handle /*error*/) {
  44. freereq* pr = static_cast<freereq*>(arg);
  45. gpr_mu_lock(pr->mu);
  46. pr->done = 1;
  47. GRPC_LOG_IF_ERROR(
  48. "pollset_kick",
  49. grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  50. gpr_mu_unlock(pr->mu);
  51. }
  52. void grpc_free_port_using_server(int port) {
  53. grpc_http_request req;
  54. grpc_http_response rsp;
  55. freereq pr;
  56. grpc_closure* shutdown_closure;
  57. grpc_init();
  58. {
  59. grpc_core::ExecCtx exec_ctx;
  60. pr = {};
  61. memset(&req, 0, sizeof(req));
  62. rsp = {};
  63. grpc_pollset* pollset =
  64. static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  65. grpc_pollset_init(pollset, &pr.mu);
  66. pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  67. shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
  68. grpc_schedule_on_exec_ctx);
  69. std::string path = absl::StrFormat("/drop/%d", port);
  70. auto uri = grpc_core::URI::Create("https", GRPC_PORT_SERVER_ADDRESS, path,
  71. {} /* query params */, "" /* fragment */);
  72. GPR_ASSERT(uri.ok());
  73. auto http_request = grpc_core::HttpRequest::Get(
  74. std::move(*uri), nullptr /* channel args */, &pr.pops, &req,
  75. grpc_core::ExecCtx::Get()->Now() + grpc_core::Duration::Seconds(30),
  76. GRPC_CLOSURE_CREATE(freed_port_from_server, &pr,
  77. grpc_schedule_on_exec_ctx),
  78. &rsp,
  79. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  80. nullptr /* insecure credentials */));
  81. http_request->Start();
  82. grpc_core::ExecCtx::Get()->Flush();
  83. gpr_mu_lock(pr.mu);
  84. while (!pr.done) {
  85. grpc_pollset_worker* worker = nullptr;
  86. if (!GRPC_LOG_IF_ERROR(
  87. "pollset_work",
  88. grpc_pollset_work(grpc_polling_entity_pollset(&pr.pops), &worker,
  89. grpc_core::ExecCtx::Get()->Now() +
  90. grpc_core::Duration::Seconds(1)))) {
  91. pr.done = 1;
  92. }
  93. }
  94. gpr_mu_unlock(pr.mu);
  95. grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
  96. shutdown_closure);
  97. grpc_http_response_destroy(&rsp);
  98. }
  99. grpc_shutdown();
  100. }
  101. typedef struct portreq {
  102. gpr_mu* mu = nullptr;
  103. grpc_polling_entity pops = {};
  104. int port = 0;
  105. int retries = 0;
  106. char* server = nullptr;
  107. grpc_http_response response = {};
  108. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request;
  109. } portreq;
  110. static void got_port_from_server(void* arg, grpc_error_handle error) {
  111. size_t i;
  112. int port = 0;
  113. portreq* pr = static_cast<portreq*>(arg);
  114. pr->http_request.reset();
  115. int failed = 0;
  116. grpc_http_response* response = &pr->response;
  117. if (error != GRPC_ERROR_NONE) {
  118. failed = 1;
  119. gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]",
  120. grpc_error_std_string(error).c_str());
  121. } else if (response->status != 200) {
  122. failed = 1;
  123. gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
  124. response->status);
  125. }
  126. if (failed) {
  127. grpc_http_request req;
  128. memset(&req, 0, sizeof(req));
  129. if (pr->retries >= 5) {
  130. gpr_mu_lock(pr->mu);
  131. pr->port = 0;
  132. GRPC_LOG_IF_ERROR(
  133. "pollset_kick",
  134. grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  135. gpr_mu_unlock(pr->mu);
  136. return;
  137. }
  138. GPR_ASSERT(pr->retries < 10);
  139. gpr_sleep_until(gpr_time_add(
  140. gpr_now(GPR_CLOCK_REALTIME),
  141. gpr_time_from_millis(
  142. static_cast<int64_t>(
  143. 1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
  144. GPR_TIMESPAN)));
  145. pr->retries++;
  146. grpc_http_response_destroy(&pr->response);
  147. pr->response = {};
  148. auto uri = grpc_core::URI::Create("http", pr->server, "/get",
  149. {} /* query params */, "" /* fragment */);
  150. GPR_ASSERT(uri.ok());
  151. pr->http_request = grpc_core::HttpRequest::Get(
  152. std::move(*uri), nullptr /* channel args */, &pr->pops, &req,
  153. grpc_core::ExecCtx::Get()->Now() + grpc_core::Duration::Seconds(30),
  154. GRPC_CLOSURE_CREATE(got_port_from_server, pr,
  155. grpc_schedule_on_exec_ctx),
  156. &pr->response,
  157. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  158. nullptr /* insecure credentials */));
  159. pr->http_request->Start();
  160. return;
  161. }
  162. GPR_ASSERT(response);
  163. GPR_ASSERT(response->status == 200);
  164. for (i = 0; i < response->body_length; i++) {
  165. GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
  166. port = port * 10 + response->body[i] - '0';
  167. }
  168. GPR_ASSERT(port > 1024);
  169. gpr_mu_lock(pr->mu);
  170. pr->port = port;
  171. GRPC_LOG_IF_ERROR(
  172. "pollset_kick",
  173. grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  174. gpr_mu_unlock(pr->mu);
  175. }
  176. int grpc_pick_port_using_server(void) {
  177. grpc_http_request req;
  178. portreq pr;
  179. grpc_closure* shutdown_closure;
  180. grpc_init();
  181. {
  182. grpc_core::ExecCtx exec_ctx;
  183. pr = {};
  184. memset(&req, 0, sizeof(req));
  185. grpc_pollset* pollset =
  186. static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  187. grpc_pollset_init(pollset, &pr.mu);
  188. pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  189. shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
  190. grpc_schedule_on_exec_ctx);
  191. pr.port = -1;
  192. pr.server = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
  193. auto uri = grpc_core::URI::Create("http", GRPC_PORT_SERVER_ADDRESS, "/get",
  194. {} /* query params */, "" /* fragment */);
  195. GPR_ASSERT(uri.ok());
  196. auto http_request = grpc_core::HttpRequest::Get(
  197. std::move(*uri), nullptr /* channel args */, &pr.pops, &req,
  198. grpc_core::ExecCtx::Get()->Now() + grpc_core::Duration::Seconds(30),
  199. GRPC_CLOSURE_CREATE(got_port_from_server, &pr,
  200. grpc_schedule_on_exec_ctx),
  201. &pr.response,
  202. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  203. nullptr /*insecure credentials*/));
  204. http_request->Start();
  205. grpc_core::ExecCtx::Get()->Flush();
  206. gpr_mu_lock(pr.mu);
  207. while (pr.port == -1) {
  208. grpc_pollset_worker* worker = nullptr;
  209. if (!GRPC_LOG_IF_ERROR(
  210. "pollset_work",
  211. grpc_pollset_work(grpc_polling_entity_pollset(&pr.pops), &worker,
  212. grpc_core::ExecCtx::Get()->Now() +
  213. grpc_core::Duration::Seconds(1)))) {
  214. pr.port = 0;
  215. }
  216. }
  217. gpr_mu_unlock(pr.mu);
  218. grpc_http_response_destroy(&pr.response);
  219. grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
  220. shutdown_closure);
  221. grpc_core::ExecCtx::Get()->Flush();
  222. }
  223. grpc_shutdown();
  224. return pr.port;
  225. }
  226. #endif // GRPC_TEST_PICK_PORT