blob: a5c8c49650213229e194991148e69720f1bfb5fc [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
77void grpc_free_port_using_server(char *server, int port) {
78 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
David Garcia Quintasf72eb972016-05-03 18:28:09 -070092 grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
93 grpc_pollset_init(pollset, &pr.mu);
David Garcia Quintasc4d51122016-06-06 14:56:02 -070094 pr.pops = grpc_polling_entity_create_from_pollset(pollset);
David Garcia Quintas60449092016-05-04 20:20:04 -070095 shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops);
Craig Tiller19d7d802016-03-17 08:47:05 -070096
97 req.host = server;
98 gpr_asprintf(&path, "/drop/%d", port);
Matthew Iselin1824f052016-02-10 12:16:06 +110099 req.http.path = path;
Craig Tiller19d7d802016-03-17 08:47:05 -0700100
101 grpc_httpcli_context_init(&context);
David Garcia Quintas60449092016-05-04 20:20:04 -0700102 grpc_httpcli_get(&exec_ctx, &context, &pr.pops, &req,
Craig Tillerddad9782016-05-05 17:11:31 -0700103 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
104 grpc_closure_create(freed_port_from_server, &pr), &rsp);
Craig Tiller19d7d802016-03-17 08:47:05 -0700105 gpr_mu_lock(pr.mu);
106 while (!pr.done) {
107 grpc_pollset_worker *worker = NULL;
Craig Tiller94f84532016-05-06 21:03:29 -0700108 if (!GRPC_LOG_IF_ERROR(
109 "pollset_work",
Craig Tillerc97065d2016-06-07 13:00:14 -0700110 grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
111 &worker, gpr_now(GPR_CLOCK_MONOTONIC),
Craig Tiller94f84532016-05-06 21:03:29 -0700112 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
113 pr.done = 1;
114 }
Craig Tiller19d7d802016-03-17 08:47:05 -0700115 }
116 gpr_mu_unlock(pr.mu);
117
118 grpc_httpcli_context_destroy(&context);
119 grpc_exec_ctx_finish(&exec_ctx);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700120 grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700121 shutdown_closure);
Craig Tiller19d7d802016-03-17 08:47:05 -0700122 grpc_exec_ctx_finish(&exec_ctx);
123 gpr_free(path);
Craig Tiller45fe17f2016-05-09 13:25:52 -0700124 grpc_http_response_destroy(&rsp);
Craig Tiller19d7d802016-03-17 08:47:05 -0700125}
126
127typedef struct portreq {
128 gpr_mu *mu;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700129 grpc_polling_entity pops;
Craig Tiller19d7d802016-03-17 08:47:05 -0700130 int port;
131 int retries;
132 char *server;
133 grpc_httpcli_context *ctx;
Craig Tillerddad9782016-05-05 17:11:31 -0700134 grpc_httpcli_response response;
Craig Tiller19d7d802016-03-17 08:47:05 -0700135} portreq;
136
137static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tillerddad9782016-05-05 17:11:31 -0700138 grpc_error *error) {
Craig Tiller19d7d802016-03-17 08:47:05 -0700139 size_t i;
140 int port = 0;
141 portreq *pr = arg;
142 int failed = 0;
Craig Tillerddad9782016-05-05 17:11:31 -0700143 grpc_httpcli_response *response = &pr->response;
Craig Tiller19d7d802016-03-17 08:47:05 -0700144
Craig Tillerddad9782016-05-05 17:11:31 -0700145 if (error != GRPC_ERROR_NONE) {
Craig Tiller19d7d802016-03-17 08:47:05 -0700146 failed = 1;
Craig Tillerddad9782016-05-05 17:11:31 -0700147 const char *msg = grpc_error_string(error);
148 gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
149 grpc_error_free_string(msg);
Craig Tiller19d7d802016-03-17 08:47:05 -0700150 } else if (response->status != 200) {
151 failed = 1;
152 gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
153 response->status);
154 }
155
156 if (failed) {
157 grpc_httpcli_request req;
158 memset(&req, 0, sizeof(req));
159 GPR_ASSERT(pr->retries < 10);
160 gpr_sleep_until(gpr_time_add(
161 gpr_now(GPR_CLOCK_REALTIME),
162 gpr_time_from_millis(
163 (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
164 GPR_TIMESPAN)));
165 pr->retries++;
166 req.host = pr->server;
Matthew Iselin1824f052016-02-10 12:16:06 +1100167 req.http.path = "/get";
Craig Tillerddad9782016-05-05 17:11:31 -0700168 grpc_http_response_destroy(&pr->response);
169 memset(&pr->response, 0, sizeof(pr->response));
David Garcia Quintas60449092016-05-04 20:20:04 -0700170 grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, &req,
Craig Tillerddad9782016-05-05 17:11:31 -0700171 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
172 grpc_closure_create(got_port_from_server, pr),
173 &pr->response);
Craig Tiller19d7d802016-03-17 08:47:05 -0700174 return;
175 }
176 GPR_ASSERT(response);
177 GPR_ASSERT(response->status == 200);
178 for (i = 0; i < response->body_length; i++) {
179 GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
180 port = port * 10 + response->body[i] - '0';
181 }
182 GPR_ASSERT(port > 1024);
183 gpr_mu_lock(pr->mu);
184 pr->port = port;
Craig Tillerc97065d2016-06-07 13:00:14 -0700185 GRPC_LOG_IF_ERROR(
186 "pollset_kick",
187 grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
Craig Tiller19d7d802016-03-17 08:47:05 -0700188 gpr_mu_unlock(pr->mu);
189}
190
191int grpc_pick_port_using_server(char *server) {
192 grpc_httpcli_context context;
193 grpc_httpcli_request req;
194 portreq pr;
195 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
196 grpc_closure *shutdown_closure;
197
198 grpc_init();
199
200 memset(&pr, 0, sizeof(pr));
201 memset(&req, 0, sizeof(req));
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700202 grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
203 grpc_pollset_init(pollset, &pr.mu);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700204 pr.pops = grpc_polling_entity_create_from_pollset(pollset);
David Garcia Quintas60449092016-05-04 20:20:04 -0700205 shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops);
Craig Tiller19d7d802016-03-17 08:47:05 -0700206 pr.port = -1;
207 pr.server = server;
208 pr.ctx = &context;
209
210 req.host = server;
Matthew Iselin1824f052016-02-10 12:16:06 +1100211 req.http.path = "/get";
Craig Tiller19d7d802016-03-17 08:47:05 -0700212
213 grpc_httpcli_context_init(&context);
Craig Tillerc97065d2016-06-07 13:00:14 -0700214 grpc_httpcli_get(
215 &exec_ctx, &context, &pr.pops, &req, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
216 grpc_closure_create(got_port_from_server, &pr), &pr.response);
Craig Tiller19d7d802016-03-17 08:47:05 -0700217 grpc_exec_ctx_finish(&exec_ctx);
218 gpr_mu_lock(pr.mu);
219 while (pr.port == -1) {
220 grpc_pollset_worker *worker = NULL;
Craig Tiller94f84532016-05-06 21:03:29 -0700221 if (!GRPC_LOG_IF_ERROR(
222 "pollset_work",
Craig Tillerc97065d2016-06-07 13:00:14 -0700223 grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
224 &worker, gpr_now(GPR_CLOCK_MONOTONIC),
Craig Tiller94f84532016-05-06 21:03:29 -0700225 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
226 pr.port = 0;
227 }
Craig Tiller19d7d802016-03-17 08:47:05 -0700228 }
229 gpr_mu_unlock(pr.mu);
230
Craig Tillerddad9782016-05-05 17:11:31 -0700231 grpc_http_response_destroy(&pr.response);
Craig Tiller19d7d802016-03-17 08:47:05 -0700232 grpc_httpcli_context_destroy(&context);
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700233 grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700234 shutdown_closure);
Craig Tiller19d7d802016-03-17 08:47:05 -0700235 grpc_exec_ctx_finish(&exec_ctx);
236
237 return pr.port;
238}
239
240#endif // GRPC_TEST_PICK_PORT