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_blocking();
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