port.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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/iomgr/port.h"
  19. #include "test/core/util/test_config.h"
  20. #if defined(GRPC_TEST_PICK_PORT)
  21. #include <stdbool.h>
  22. #include <stdio.h>
  23. #include <string.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 "src/core/lib/address_utils/sockaddr_utils.h"
  29. #include "src/core/lib/http/httpcli.h"
  30. #include "src/core/lib/iomgr/resolve_address.h"
  31. #include "test/core/util/port.h"
  32. #include "test/core/util/port_server_client.h"
  33. static int* chosen_ports = nullptr;
  34. static size_t num_chosen_ports = 0;
  35. static grpc_core::Mutex* g_default_port_picker_mu;
  36. static gpr_once g_default_port_picker_init = GPR_ONCE_INIT;
  37. static void init_default_port_picker() {
  38. g_default_port_picker_mu = new grpc_core::Mutex();
  39. }
  40. static int free_chosen_port_locked(int port) {
  41. size_t i;
  42. int found = 0;
  43. size_t found_at = 0;
  44. /* Find the port and erase it from the list, then tell the server it can be
  45. freed. */
  46. for (i = 0; i < num_chosen_ports; i++) {
  47. if (chosen_ports[i] == port) {
  48. GPR_ASSERT(found == 0);
  49. found = 1;
  50. found_at = i;
  51. }
  52. }
  53. if (found) {
  54. chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1];
  55. num_chosen_ports--;
  56. grpc_free_port_using_server(port);
  57. }
  58. return found;
  59. }
  60. static void free_chosen_ports(void) {
  61. grpc_core::MutexLock lock(g_default_port_picker_mu);
  62. size_t i;
  63. grpc_init();
  64. for (i = 0; i < num_chosen_ports; i++) {
  65. grpc_free_port_using_server(chosen_ports[i]);
  66. }
  67. grpc_shutdown();
  68. gpr_free(chosen_ports);
  69. }
  70. static void chose_port_locked(int port) {
  71. if (chosen_ports == nullptr) {
  72. atexit(free_chosen_ports);
  73. }
  74. num_chosen_ports++;
  75. chosen_ports = static_cast<int*>(
  76. gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports));
  77. chosen_ports[num_chosen_ports - 1] = port;
  78. }
  79. static int grpc_pick_unused_port_impl(void) {
  80. gpr_once_init(&g_default_port_picker_init, init_default_port_picker);
  81. grpc_core::MutexLock lock(g_default_port_picker_mu);
  82. int port = grpc_pick_port_using_server();
  83. if (port != 0) {
  84. chose_port_locked(port);
  85. }
  86. return port;
  87. }
  88. static int grpc_pick_unused_port_or_die_impl(void) {
  89. int port = grpc_pick_unused_port();
  90. if (port == 0) {
  91. fprintf(stderr,
  92. "gRPC tests require a helper port server to allocate ports used \n"
  93. "during the test.\n\n"
  94. "This server is not currently running.\n\n"
  95. "To start it, run tools/run_tests/start_port_server.py\n\n");
  96. exit(1);
  97. }
  98. return port;
  99. }
  100. static void grpc_recycle_unused_port_impl(int port) {
  101. gpr_once_init(&g_default_port_picker_init, init_default_port_picker);
  102. grpc_core::MutexLock lock(g_default_port_picker_mu);
  103. GPR_ASSERT(free_chosen_port_locked(port));
  104. }
  105. static grpc_pick_port_functions g_pick_port_functions = {
  106. grpc_pick_unused_port_impl, grpc_pick_unused_port_or_die_impl,
  107. grpc_recycle_unused_port_impl};
  108. int grpc_pick_unused_port(void) {
  109. return g_pick_port_functions.pick_unused_port_fn();
  110. }
  111. int grpc_pick_unused_port_or_die(void) {
  112. return g_pick_port_functions.pick_unused_port_or_die_fn();
  113. }
  114. void grpc_recycle_unused_port(int port) {
  115. g_pick_port_functions.recycle_unused_port_fn(port);
  116. }
  117. void grpc_set_pick_port_functions(grpc_pick_port_functions functions) {
  118. GPR_ASSERT(functions.pick_unused_port_fn != nullptr);
  119. GPR_ASSERT(functions.pick_unused_port_or_die_fn != nullptr);
  120. GPR_ASSERT(functions.recycle_unused_port_fn != nullptr);
  121. g_pick_port_functions = functions;
  122. }
  123. #endif /* GRPC_TEST_PICK_PORT */