blob: a851d01635523db8a0618604b30b46784fef318a [file] [log] [blame]
Craig Tiller19d7d802016-03-17 08:47:05 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tiller19d7d802016-03-17 08:47:05 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include <grpc/support/port_platform.h>
35#include "test/core/util/test_config.h"
36
37#ifdef GRPC_TEST_PICK_PORT
38#include "test/core/util/port_server_client.h"
39
40#include <math.h>
41#include <string.h>
42
43#include <grpc/grpc.h>
44#include <grpc/support/alloc.h>
45#include <grpc/support/log.h>
46#include <grpc/support/string_util.h>
47#include <grpc/support/sync.h>
48#include <grpc/support/time.h>
49
Craig Tiller9533d042016-03-25 17:11:06 -070050#include "src/core/lib/http/httpcli.h"
Craig Tiller19d7d802016-03-17 08:47:05 -070051
52typedef struct freereq {
53 gpr_mu *mu;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070054 grpc_polling_entity pops;
Craig Tiller19d7d802016-03-17 08:47:05 -070055 int done;
56} freereq;
57
David Garcia Quintasf72eb972016-05-03 18:28:09 -070058static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p,
Craig Tillerc97065d2016-06-07 13:00:14 -070059 grpc_error *error) {
David Garcia Quintasc4d51122016-06-06 14:56:02 -070060 grpc_pollset *pollset = grpc_polling_entity_pollset(p);
David Garcia Quintasf72eb972016-05-03 18:28:09 -070061 grpc_pollset_destroy(pollset);
62 gpr_free(pollset);
Craig Tiller19d7d802016-03-17 08:47:05 -070063 grpc_shutdown();
64}
65
66static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tillerddad9782016-05-05 17:11:31 -070067 grpc_error *error) {
Craig Tiller19d7d802016-03-17 08:47:05 -070068 freereq *pr = arg;
69 gpr_mu_lock(pr->mu);
70 pr->done = 1;
Craig Tillerc97065d2016-06-07 13:00:14 -070071 GRPC_LOG_IF_ERROR(
72 "pollset_kick",
73 grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
Craig Tiller19d7d802016-03-17 08:47:05 -070074 gpr_mu_unlock(pr->mu);
75}
76
Craig Tillercba864b2017-02-17 10:27:56 -080077void grpc_free_port_using_server(int port) {
Craig Tiller19d7d802016-03-17 08:47:05 -070078 grpc_httpcli_context context;
79 grpc_httpcli_request req;
Craig Tillerddad9782016-05-05 17:11:31 -070080 grpc_httpcli_response rsp;
Craig Tiller19d7d802016-03-17 08:47:05 -070081 freereq pr;
82 char *path;
83 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
84 grpc_closure *shutdown_closure;
85
86 grpc_init();
87
88 memset(&pr, 0, sizeof(pr));
89 memset(&req, 0, sizeof(req));
Craig Tillerddad9782016-05-05 17:11:31 -070090 memset(&rsp, 0, sizeof(rsp));
Craig Tiller19d7d802016-03-17 08:47:05 -070091
Yuchen Zeng47de64c2017-02-22 19:04:38 -080092 grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
David Garcia Quintasf72eb972016-05-03 18:28:09 -070093 grpc_pollset_init(pollset, &pr.mu);
David Garcia Quintasc4d51122016-06-06 14:56:02 -070094 pr.pops = grpc_polling_entity_create_from_pollset(pollset);
Craig Tiller91031da2016-12-28 15:44:25 -080095 shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
96 grpc_schedule_on_exec_ctx);
Craig Tiller19d7d802016-03-17 08:47:05 -070097
Craig Tillercba864b2017-02-17 10:27:56 -080098 req.host = GRPC_PORT_SERVER_ADDRESS;
Craig Tiller19d7d802016-03-17 08:47:05 -070099 gpr_asprintf(&path, "/drop/%d", port);
Matthew Iselin1824f052016-02-10 12:16:06 +1100100 req.http.path = path;
Craig Tiller19d7d802016-03-17 08:47:05 -0700101
102 grpc_httpcli_context_init(&context);
Craig Tiller20afa3d2016-10-17 14:52:14 -0700103 grpc_resource_quota *resource_quota =
104 grpc_resource_quota_create("port_server_client/free");
105 grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req,
Robbie Shadeca7effc2017-01-17 09:14:29 -0500106 grpc_timeout_seconds_to_deadline(10),
Craig Tiller91031da2016-12-28 15:44:25 -0800107 grpc_closure_create(freed_port_from_server, &pr,
108 grpc_schedule_on_exec_ctx),
109 &rsp);
Craig Tillera59c16c2016-10-31 07:25:01 -0700110 grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
Craig Tiller19d7d802016-03-17 08:47:05 -0700111 gpr_mu_lock(pr.mu);
112 while (!pr.done) {
113 grpc_pollset_worker *worker = NULL;
Craig Tiller94f84532016-05-06 21:03:29 -0700114 if (!GRPC_LOG_IF_ERROR(
115 "pollset_work",
Craig Tillerc97065d2016-06-07 13:00:14 -0700116 grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
117 &worker, gpr_now(GPR_CLOCK_MONOTONIC),
Robbie Shadeca7effc2017-01-17 09:14:29 -0500118 grpc_timeout_seconds_to_deadline(1)))) {
Craig Tiller94f84532016-05-06 21:03:29 -0700119 pr.done = 1;
120 }
Craig Tiller19d7d802016-03-17 08:47:05 -0700121 }
122 gpr_mu_unlock(pr.mu);
123
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800124 grpc_httpcli_context_destroy(&exec_ctx, &context);
Craig Tiller19d7d802016-03-17 08:47:05 -0700125 grpc_exec_ctx_finish(&exec_ctx);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700126 grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700127 shutdown_closure);
Craig Tiller19d7d802016-03-17 08:47:05 -0700128 grpc_exec_ctx_finish(&exec_ctx);
129 gpr_free(path);
Craig Tiller45fe17f2016-05-09 13:25:52 -0700130 grpc_http_response_destroy(&rsp);
Craig Tiller19d7d802016-03-17 08:47:05 -0700131}
132
133typedef struct portreq {
134 gpr_mu *mu;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700135 grpc_polling_entity pops;
Craig Tiller19d7d802016-03-17 08:47:05 -0700136 int port;
137 int retries;
138 char *server;
139 grpc_httpcli_context *ctx;
Craig Tillerddad9782016-05-05 17:11:31 -0700140 grpc_httpcli_response response;
Craig Tiller19d7d802016-03-17 08:47:05 -0700141} portreq;
142
143static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tillerddad9782016-05-05 17:11:31 -0700144 grpc_error *error) {
Craig Tiller19d7d802016-03-17 08:47:05 -0700145 size_t i;
146 int port = 0;
147 portreq *pr = arg;
148 int failed = 0;
Craig Tillerddad9782016-05-05 17:11:31 -0700149 grpc_httpcli_response *response = &pr->response;
Craig Tiller19d7d802016-03-17 08:47:05 -0700150
Craig Tillerddad9782016-05-05 17:11:31 -0700151 if (error != GRPC_ERROR_NONE) {
Craig Tiller19d7d802016-03-17 08:47:05 -0700152 failed = 1;
Craig Tillerddad9782016-05-05 17:11:31 -0700153 const char *msg = grpc_error_string(error);
154 gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800155
Craig Tiller19d7d802016-03-17 08:47:05 -0700156 } else if (response->status != 200) {
157 failed = 1;
158 gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
159 response->status);
160 }
161
162 if (failed) {
163 grpc_httpcli_request req;
164 memset(&req, 0, sizeof(req));
165 GPR_ASSERT(pr->retries < 10);
166 gpr_sleep_until(gpr_time_add(
167 gpr_now(GPR_CLOCK_REALTIME),
168 gpr_time_from_millis(
169 (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
170 GPR_TIMESPAN)));
171 pr->retries++;
172 req.host = pr->server;
Matthew Iselin1824f052016-02-10 12:16:06 +1100173 req.http.path = "/get";
Craig Tillerddad9782016-05-05 17:11:31 -0700174 grpc_http_response_destroy(&pr->response);
175 memset(&pr->response, 0, sizeof(pr->response));
Craig Tiller20afa3d2016-10-17 14:52:14 -0700176 grpc_resource_quota *resource_quota =
177 grpc_resource_quota_create("port_server_client/pick_retry");
178 grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req,
Robbie Shadeca7effc2017-01-17 09:14:29 -0500179 grpc_timeout_seconds_to_deadline(10),
Craig Tiller91031da2016-12-28 15:44:25 -0800180 grpc_closure_create(got_port_from_server, pr,
181 grpc_schedule_on_exec_ctx),
Craig Tillerddad9782016-05-05 17:11:31 -0700182 &pr->response);
Craig Tillera59c16c2016-10-31 07:25:01 -0700183 grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
Craig Tiller19d7d802016-03-17 08:47:05 -0700184 return;
185 }
186 GPR_ASSERT(response);
187 GPR_ASSERT(response->status == 200);
188 for (i = 0; i < response->body_length; i++) {
189 GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
190 port = port * 10 + response->body[i] - '0';
191 }
192 GPR_ASSERT(port > 1024);
193 gpr_mu_lock(pr->mu);
194 pr->port = port;
Craig Tillerc97065d2016-06-07 13:00:14 -0700195 GRPC_LOG_IF_ERROR(
196 "pollset_kick",
197 grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
Craig Tiller19d7d802016-03-17 08:47:05 -0700198 gpr_mu_unlock(pr->mu);
199}
200
Craig Tillercba864b2017-02-17 10:27:56 -0800201int grpc_pick_port_using_server(void) {
Craig Tiller19d7d802016-03-17 08:47:05 -0700202 grpc_httpcli_context context;
203 grpc_httpcli_request req;
204 portreq pr;
205 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
206 grpc_closure *shutdown_closure;
207
208 grpc_init();
209
210 memset(&pr, 0, sizeof(pr));
211 memset(&req, 0, sizeof(req));
Yuchen Zeng47de64c2017-02-22 19:04:38 -0800212 grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700213 grpc_pollset_init(pollset, &pr.mu);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700214 pr.pops = grpc_polling_entity_create_from_pollset(pollset);
Craig Tiller91031da2016-12-28 15:44:25 -0800215 shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
216 grpc_schedule_on_exec_ctx);
Craig Tiller19d7d802016-03-17 08:47:05 -0700217 pr.port = -1;
Craig Tillercba864b2017-02-17 10:27:56 -0800218 pr.server = GRPC_PORT_SERVER_ADDRESS;
Craig Tiller19d7d802016-03-17 08:47:05 -0700219 pr.ctx = &context;
220
Craig Tillercba864b2017-02-17 10:27:56 -0800221 req.host = GRPC_PORT_SERVER_ADDRESS;
Matthew Iselin1824f052016-02-10 12:16:06 +1100222 req.http.path = "/get";
Craig Tiller19d7d802016-03-17 08:47:05 -0700223
224 grpc_httpcli_context_init(&context);
Craig Tiller20afa3d2016-10-17 14:52:14 -0700225 grpc_resource_quota *resource_quota =
226 grpc_resource_quota_create("port_server_client/pick");
Craig Tiller91031da2016-12-28 15:44:25 -0800227 grpc_httpcli_get(
228 &exec_ctx, &context, &pr.pops, resource_quota, &req,
Robbie Shadeca7effc2017-01-17 09:14:29 -0500229 grpc_timeout_seconds_to_deadline(10),
Craig Tiller91031da2016-12-28 15:44:25 -0800230 grpc_closure_create(got_port_from_server, &pr, grpc_schedule_on_exec_ctx),
231 &pr.response);
Craig Tillera59c16c2016-10-31 07:25:01 -0700232 grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
Craig Tiller19d7d802016-03-17 08:47:05 -0700233 grpc_exec_ctx_finish(&exec_ctx);
234 gpr_mu_lock(pr.mu);
235 while (pr.port == -1) {
236 grpc_pollset_worker *worker = NULL;
Craig Tiller94f84532016-05-06 21:03:29 -0700237 if (!GRPC_LOG_IF_ERROR(
238 "pollset_work",
Craig Tillerc97065d2016-06-07 13:00:14 -0700239 grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
240 &worker, gpr_now(GPR_CLOCK_MONOTONIC),
Robbie Shadeca7effc2017-01-17 09:14:29 -0500241 grpc_timeout_seconds_to_deadline(1)))) {
Craig Tiller94f84532016-05-06 21:03:29 -0700242 pr.port = 0;
243 }
Craig Tiller19d7d802016-03-17 08:47:05 -0700244 }
245 gpr_mu_unlock(pr.mu);
246
Craig Tillerddad9782016-05-05 17:11:31 -0700247 grpc_http_response_destroy(&pr.response);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800248 grpc_httpcli_context_destroy(&exec_ctx, &context);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700249 grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700250 shutdown_closure);
Craig Tiller19d7d802016-03-17 08:47:05 -0700251 grpc_exec_ctx_finish(&exec_ctx);
252
253 return pr.port;
254}
255
256#endif // GRPC_TEST_PICK_PORT