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